成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费

資訊專欄INFORMATION COLUMN

shadow-cljs: JavaScript 依賴的實(shí)踐

張漢慶 / 2611人閱讀

摘要:原文原作者是作者是一個(gè)面向開發(fā)者友好的編譯器之前關(guān)于依賴的文章問(wèn)題前景里面我解釋了為什么當(dāng)中采用了和默認(rèn)的方案不同的做法簡(jiǎn)單回顧下或者的寫法難以擴(kuò)張自定義的打包實(shí)際當(dāng)中使用繁瑣目前對(duì)大部分的模塊的處理不夠可靠自定義了一個(gè)而移除了

原文 https://code.thheller.com/blo...
原作者是 shadow-cljs 作者, shadow-cljs 是一個(gè)面向 JavaScript 開發(fā)者友好的 ClojureScript 編譯器.

之前關(guān)于 js 依賴的文章(問(wèn)題, 前景)里面, 我解釋了為什么 shadow-cljs 當(dāng)中采用了和 ClojureScript 默認(rèn)的方案不同的做法. 簡(jiǎn)單回顧下:

cljsjs 或者 :foreign-libs 的寫法難以擴(kuò)張

自定義的打包實(shí)際當(dāng)中使用繁瑣

Closure Compiler 目前對(duì)大部分的 npm 模塊的處理不夠可靠

shadow-cljs 自定義了一個(gè) js bundler, 而移除了 :foreign-libs 的支持

安裝 js 依賴

幾乎所有的 npm 模塊都會(huì)寫一遍如何安裝. 現(xiàn)在對(duì)于 shadow-cljs 來(lái)說(shuō)也是適用的. 比如有個(gè)類庫(kù)要你運(yùn)行:

npm install the-thing

你照做就好. 不需要其他步驟了. 當(dāng)然你喜歡的話可以用 yarn. 然后依賴就會(huì)被寫進(jìn) package.json 文件用于管理. 如果沒有 package.json 那就運(yùn)行 npm init.

上面說(shuō)到這些東西, 你可以用這個(gè) QuickStart 模板 來(lái)試用.

試用 js 依賴

大部分的 npm 模塊也會(huì)寫一下具體的代碼表示怎樣使用模塊. "舊的" CommonJS 的寫法是用 require 調(diào)用. 翻譯到 ClojureScript 就是:

var react = require("react");
(ns my.app
  (:require ["react" :as react]))

不管 "string" 參數(shù)的地方用了什么然后被 require 調(diào)用, 我們都是這樣換成 ns :require. :as 的 alias 部分就隨你定義. 有了這個(gè)之后, 它就像是其他的 cljs 的命名空間那樣可以調(diào)用了:

(react/createElement "div" nil "helle world")

這跟以前 :foreign-libs 或者 CLJSJS 當(dāng)中做的不一樣, 以前比如引入了 thingns 然后要用 js/Thing(或者其他全局導(dǎo)出的變量)來(lái)使用代碼. 現(xiàn)在可以用 ns 格式以及 :as 后面提供的名稱. 需要的話還可以寫 :refer:rename.

一些模塊會(huì)暴露一個(gè)函數(shù), 那你可以寫 (:require ["thing" as thing]) 然后調(diào)用 (thing).

最近一些模塊開始用 ES6 的 import 語(yǔ)法作為例子了. 這些代碼除了一個(gè) default 寫法以外, 基本上在 ClojureScript 能做到一一對(duì)應(yīng). 比如說(shuō)翻譯下面的例子:

import defaultExport from "module-name";
import * as name from "module-name";
import { export } from "module-name";
import { export as alias } from "module-name";
import { export1 , export2 } from "module-name";
import { export1 , export2 as alias2 , [...] } from "module-name";
import defaultExport, { export [ , [...] ] } from "module-name";
import defaultExport, * as name from "module-name";
import "module-name";

到(包裹在 ns 里面的):

(:require ["module-name" :default defaultExport])
(:require ["module-name" :as name])
(:require ["module-name" :refer (export)])
(:require ["module-name" :rename {export alias}])
(:require ["module-name" :refer (export1) :rename {export2 alias2}])
(:require ["module-name" :refer (export) :default defaultExport])
(:require ["module-name" :as name :default defaultExport])
(:require ["module-name"])

其中 :default 參數(shù)目前只在 shadow-cljs 里面支持, 但是你也可以在這里投票幫助它進(jìn)入到規(guī)范當(dāng)中. 或者你也可以一直用 :as alias 然后調(diào)用 alias/default, 這樣你覺得能個(gè)標(biāo)準(zhǔn)的 cljs 始終保持兼容的話. 我覺得吧, 對(duì)于某些模塊來(lái)說(shuō)啰嗦了點(diǎn).

新的可能性

之前我們的使用打包之后的代碼, 可能會(huì)包含我們用不到的代碼. 某些模塊也說(shuō)明了一些辦法可以只引入部分的模塊, 這樣最終構(gòu)建的代碼體積會(huì)小一些.

react-virtualized 有個(gè)這樣的例子:

// You can import any component you want as a named export from "react-virtualized", eg
import { Column, Table } from "react-virtualized"

// But if you only use a few react-virtualized components,
// And you"re concerned about increasing your application"s bundle size,
// You can directly import only the components you need, like so:
import AutoSizer from "react-virtualized/dist/commonjs/AutoSizer"
import List from "react-virtualized/dist/commonjs/List"

那么很容易翻譯過(guò)去:

;; all
(:require ["react-virtualized" :refer (Column Table)])
;; one by one
(:require ["react-virtualized/dist/commonjs/AutoSizer" :default virtual-auto-sizer])
(:require ["react-virtualized/dist/commonjs/List" :default virtual-list])
查找 js 依賴

默認(rèn)情況下 shadow-cljs 通過(guò) npm 的方式引用查找所有 (:require ["thing" :as x]). 也就是說(shuō)會(huì)查找 /node_modules/thing/... 當(dāng)中的代碼. 為了對(duì)這個(gè)行為進(jìn)行自定義, shadow-cljs 暴露了一個(gè) :resolve 配置項(xiàng), 你可以自己定義某些模塊如何查找.

使用 CDN

比如說(shuō)頁(yè)面里的 React 從 CDN 上引用了. 這時(shí)候按說(shuō)你可以用 js/React 了, 但是最好還是不要這樣. 你應(yīng)該是繼續(xù)用 (:require ["react" :as react]), 同時(shí)在 shadow-cljs 里定義 react 怎樣查找. 這個(gè)配置在 shadow-cljs.edn 文件里配置:

{:builds
 {:app
  {:target :browser
   ...
   :js-options
   {:resolve {"react" {:target :global
                       :global "React"}}}}

  :server
  {:target :node-script
   ...}}}

現(xiàn)在 :app 這個(gè)構(gòu)建會(huì)使用全局的 React 實(shí)例, 而在 :server 這個(gè)構(gòu)建當(dāng)中會(huì)繼續(xù)使用 react 的 npm 模塊. 不需要額外折騰代碼去完成需求.

重定向 require

某些模塊提供多個(gè) "dist" 文件, 然后可能默認(rèn)的那個(gè)剛好是在 shadow-cljs 里有問(wèn)題的. 一個(gè)明顯的例子就是 d3. 他們默認(rèn)的 "main" 指向 build/d3.node.js, 這個(gè)不是在瀏覽器里面用的版本. 他們的 ES6 代碼還觸發(fā)了 Closure Compiler 里的一個(gè) bug, 所以我們不能用. 這樣的話我們就重定向到其他的引用去:

{:resolve {"d3" {:target :npm
                 :require "d3/build/d3.js"}}}

你也可以直接就寫 (:require ["d3/build/d3.js" :as d3]), 如果你只關(guān)心瀏覽器當(dāng)中的使用的話.

使用本地文件

你還可以用 :resolve 來(lái)直接映射到一個(gè)項(xiàng)目中的本地文件:

{:resolve {"my-thing" {:target :file
                       :file "path/to/file.js"}}}

這里的 :file 總是相對(duì)于項(xiàng)目根路徑. 這個(gè)文件里可以用 require 或者 import/export, 這些隨后都會(huì)被處理好的.

遷移 cljsjs.*

很多 cljs 類庫(kù)還在用 CLJSJS 包, 它們?cè)?shadow-cljs 里不能正常使用了, 因?yàn)?:foreign-libs 不再支持. 我提供了一個(gè)清晰的遷移路線, 只需要增加一個(gè) shim 文件把 cljsjs.thing 映射回到原始的 npm 模塊, 然后把全局變量暴露出去.

比如 react 需要一個(gè)這樣的文件src/cljsjs/react.cljs:

(ns cljsjs.react
  (:require ["react" :as react]
            ["create-react-class" :as crc]))

(js/goog.object.set react "createClass" crc)
(js/goog.exportSymbol "React" react)

因?yàn)檫@樣的話每個(gè)人手動(dòng)處理會(huì)麻煩, 所以我提供了 shadow-cljsjs 這個(gè)類庫(kù)來(lái)提供這個(gè)功能. 雖然不會(huì)包含每一個(gè)模塊, 但是我會(huì)持續(xù)添加. 歡迎來(lái)幫忙貢獻(xiàn)模塊.

不過(guò)它僅僅提供 shim 文件. 你還是需要用 npm install 安裝真實(shí)的模塊.

其他功能不能用怎么辦?

JavaScript 社區(qū)變化很快, 并不是每個(gè)人都一樣地寫代碼, 都一樣地分發(fā)代碼, 有些東西是 shadow-cljs 不能自動(dòng)處理或者需要自定義 :resolve 配置的. 可能是會(huì)遇到 bug, 畢竟都是新東西.

遇到任何模塊不能按照預(yù)期地使用, 請(qǐng)報(bào)告. 在 #shadow-cljs 很容易找到我.

關(guān)于這篇文章的討論請(qǐng)移步 :clojurevese.

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/89693.html

相關(guān)文章

  • Luxon 初步介紹(Moment 團(tuán)隊(duì)日期另一個(gè)類庫(kù))

    摘要:我不是的深度用戶只是日常會(huì)遇到一些時(shí)間格式化的需求之前用的都是不過(guò)對(duì)的感到有些不舒服同事介紹過(guò)里邊用不可變數(shù)據(jù)的風(fēng)格設(shè)計(jì)的所以就試試上星星很多請(qǐng)放心食用是項(xiàng)目的某個(gè)維護(hù)者開發(fā)的按照他個(gè)人想法進(jìn)行了改進(jìn)除了不可變性使用的工具做了更新也嘗試到時(shí) 我不是 Moment 的深度用戶, 只是日常會(huì)遇到一些時(shí)間格式化的需求,之前用的都是 Moment, 不過(guò)對(duì) Moment 的 mutable A...

    stormzhang 評(píng)論0 收藏0
  • 前端每周清單第 40 期: JS Core 與 Cost,Node 內(nèi)存溢出調(diào)試,Softwar

    摘要:已被所有主流瀏覽器支持在過(guò)去幾周蘋果的瀏覽器與微軟的瀏覽器分別發(fā)布新版本,支持了,再加上早已支持的和,已得到所有主流瀏覽器支持。 showImg(https://segmentfault.com/img/remote/1460000012086220?w=1240&h=823); 前端每周清單第 40 期: JS 的 Core 與 Cost,Node 內(nèi)存溢出調(diào)試,Software 2...

    番茄西紅柿 評(píng)論0 收藏0
  • 預(yù)告:JavaScript模塊全覽

    摘要:之前寫的文章急速全棧教程得到了不錯(cuò)的閱讀量,霸屏掘金頭條天,點(diǎn)贊過(guò)千,閱讀近萬(wàn),甚至還有人在評(píng)論區(qū)打廣告,可見也是一個(gè)小小的生態(tài)了。今天看到的霸屏的,也是講全棧的,見參考文章接下來(lái)要寫的是模塊。全局命名污染和命名沖突依賴管理。 之前寫的文章急速Js全棧教程得到了不錯(cuò)的閱讀量,霸屏掘金頭條3天,點(diǎn)贊過(guò)千,閱讀近萬(wàn),甚至還有人在評(píng)論區(qū)打廣告,可見也是一個(gè)小小的生態(tài)了;)??磥?lái)和JS全棧有關(guān)...

    focusj 評(píng)論0 收藏0
  • RequireJS配置項(xiàng)筆記

    摘要:讀不順中文文檔,對(duì)應(yīng)中文文檔,自行翻譯的如果有問(wèn)題錯(cuò)誤,歡迎指點(diǎn)修改配置選項(xiàng)方法一在頂級(jí)頁(yè)面或頂級(jí)腳本文件沒有定義模塊的腳本文件中配置方法二在主模塊中配置缺點(diǎn)主模塊異步加載,多入口的話,會(huì)隨機(jī)報(bào)錯(cuò)方法三在調(diào)用之前,將配置定義為全局變量配置在 讀不順中文文檔,對(duì)應(yīng)中文文檔,自行翻譯的……如果有問(wèn)題/錯(cuò)誤,歡迎指點(diǎn); 修改配置選項(xiàng): 方法一、 requi...

    FWHeart 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

最新活動(dòng)
閱讀需要支付1元查看
<