以前講了不少關於項目工程化、前端架構、前端構建等方面的技術,此次說說怎麼寫一個完美的第三方庫。css
js
模塊化的發展大體有這樣一個過程 iife => commonjs/amd => es6
,而在這幾個規範中:前端
iife
: js
原生支持,但通常不會直接使用這種規範寫代碼amd
: requirejs
定義的加載規範,但隨着構建工具的出現,便通常不會用這種規範寫代碼commonjs
: node
的模塊加載規範,通常會用這種規範寫 node
程序es6
: ECMAScript2015
定義的模塊加載規範,但到目前爲止,幾乎全部的 js
運行環境都不支持,包括瀏覽器、node
(包括 electron
、nw.js
)、React Native
等針對原生不支持任何規範的運行環境程序(如瀏覽器、React Native
),建議使用 es6
規範來寫代碼,而後由工具轉換成原生 js
可以運行的。node
而針對 node
程序,能夠直接用 commonjs
規範來寫,也可由 es6
規範來寫,而後用工具轉化成 commonjs
規範。react
因此,總的來講,均可以使用 es6
規範來寫代碼,而後用工具轉換成其餘規範,並且 es6
的代碼可使用 tree-shaking
功能。webpack
參考:git
對於前端項目來講,由於有靜態資源(如圖片、字體等)加載與按需加載的需求,因此使用 webpack
是不二選擇,但對於第三方庫來講,其實還有更好的選擇:rollup
。es6
能夠查看 webpack 以外的另外一種選擇:rollup 瞭解 webpack
與 rollup
之間各自的差別與優點。github
webpack
在打包成第三方庫的時候只能導出 amd/commonjs/umd
,而 rollup
可以導出 amd/commonjs/umd/es6
。使用 rollup
導出 es6
模塊,就能夠在使用這個庫的項目中構建時使用 tree-shaking
功能。 web
對於有樣式文件(css
、less
、scss
)、靜態資源文件(圖片、字體)的前端組件來講,可使用 rollup-plugin-postcss 插件配合 rollup
處理樣式文件與靜態資源文件。express
參考:
通常庫項目的目錄:
|-- / # 項目根目錄 |-- src/ # 源代碼目錄 |-- lib/(dist/) # 發佈文件目錄 |-- test/ # 測試文件目錄 |-- ... # 更多其餘目錄
若是是多包項目(一個項目裏有多個 npm packages,好比 babel):
|-- / # 項目根目錄 |-- packages/ # packages 目錄 |-- pkg1/ # package1 目錄 |-- src/ # 源代碼目錄 |-- lib/(dist/) # 發佈文件目錄 |-- pkg2/ # package2 目錄 |-- src/ # 源代碼目錄 |-- lib/(dist/) # 發佈文件目錄 |-- ...
後面會詳細講解多包項目。
不論是應用項目仍是第三方庫項目,都須要搭建一個好的腳手架,來幫助咱們更好的編寫代碼、構建項目等。
能夠查看 搭建本身的前端腳手架 瞭解一些基本的腳手架文件與工具。
好比:
.editorconfig
: 用這個文件來統一不一樣編輯器的一些配置,好比 tab
轉 2 個空格、自動插入空尾行、去掉行尾的空格等,http://editorconfig.org git
提交以前對代碼進行審查,不然不予提交.travis.yml
: 一個很棒的持續集成服務,https://www.travis-ci.org/ 詳細的文件、工具與配置,參考 搭建本身的前端腳手架。
另外,針對開源的第三方庫,還能夠有:
LICENSE
: 協議文件CONTRIBUTING.md
: 項目代碼參與者codecov.yml
: 測試覆蓋率配置文件.github
: github
上的一些自定義配置,好比 issue
模板、pr
模板等/docs
: 文檔目錄/examples
: 使用示例目錄/scripts
: 腳本目錄加上 rollup
的配置文件 rollup.config.js
:
若是是 node
程序,把 es6
規範轉化成 commonjs
規範:
export default { input: 'src/index.js', output: { file: 'lib/index.js', format: 'cjs', }, };
若是是前端庫,還須要轉 es6+
到 es5
、導出不一樣規範的文件(es6/commonjs/amd/umd
):
import babel from 'rollup-plugin-babel'; import postcss from 'rollup-plugin-postcss'; export default [ { file: 'lib/cjs.js', format: 'cjs', }, { file: 'lib/m.js', format: 'esm', }, { file: 'lib/umd.js', format: 'umd', name: 'Name', }, { file: 'lib/amd.js', format: 'amd', }, ].map(output => ({ input: 'src/index.js', output, plugins: [ babel({ presets: ['@babel/preset-env'], }), postcss({ extract: !0 }), // 構建樣式文件時須要這個插件 ], }));
通常來講,咱們並不但願把發佈文件放到 git
的版本控制之中,而只是發佈到倉庫而已,因此:
# .gitignore .DS_Store node_modules bower_components /coverage *.log .idea .vscode .eslintcache package-lock.json /lib # 把 lib 排除在外 /packages/*/lib # 多包項目
{ ... # node 項目 "main": "lib/index.js", # 前端項目 "main": "lib/cjs.js", # commonjs 規範文件 "module": "lib/m.js", # es6 規範文件 "umd:main": "lib/umd.js", # umd 規範文件 "amd:main": "lib/amd.js", # amd 規範文件 "files": [ # 發佈時只發布 lib 目錄下文件 "lib" ], "scripts": { ... "build": "rollup -c", # 構建發佈文件 "prepublishOnly": "npm run build", # npm publish 以前先 npm run build "pretest": "npm run build", # npm run test 以前先 npm run build }, ... }
在實際項目中,構建工具(如 webpack
)會首先找這個包中的 module
字段對應的 es6
規範文件,並使用 tree-shaking
;若是不存在,而後找 main
字段對應的文件。
有些構建工具可能也會用 amd
規範文件與 umd
規範文件。
參考:
若是一個項目很大,須要分割成多個 npm
包進行管理,但這些包仍然在一個項目裏,而且這些包可能有相互依賴關係,這個時候就比較難以管理和開發了。
爲了方便的管理多包項目,lerna 便應運而生,babel、create-react-app、jest、lila 等都是用 lerna
來管理多個包的。
英文很差的童鞋,能夠參考 使用lerna管理大型前端項目,瞭解 lerna
的一些基本用法。
my-lerna-repo/ package.json packages/ package-1/ package.json package-2/ package.json
# 安裝 npm i -g lerna
# 初始化 git init lerna-repo && cd lerna-repo lerna init
# 初始化後的目錄及文件 lerna-repo/ packages/ package.json lerna.json
{ "version": "0.5.2", # 當前版本號 "packages": [ "packages/*" ], "command": { "publish": { # 發佈配置 "ignoreChanges": [ # 哪些文件變更不會引起發佈新版本 "*.md", "*.json", "*.txt", "test/**", "example/**", "package.json" ] }, "bootstrap": { "npmClient": "cnpm" # lerna bootstrap 時使用哪一個 npm 客戶端 } }, "npmClientArgs": [ # npm 客戶端 運行時的參數 "--no-package-lock" ] }
lerna publish
: 發佈全部有更新的包在默認的固定模式(Fixed mode)下,這個命令會檢查 packages
目錄下哪些包的文件有更新(lerna.json
中 command.publish.ignoreChanges
除外),而後把 lerna.json
中的 version
與有更新的包中 package.json
的 version
字段更新到一個新的版本號上,最後把這些有更新的包都發布到遠程倉庫上。
lerna bootstrap
: 啓動創建包相互之間的 node_modules
連接這個命令會根據各個包下 package.json
裏面的 dependencies
和 devDependencies
配置,使用 symlink
在各個包的 node_modules
下面創建引用關係。這樣就解決了相互之間有依賴而沒法聯調的問題。
lerna changed
: 查看哪些包有更新,能夠發佈一個新的版本lerna diff [package?]
: 查看包都更新了些什麼lerna run [script]
: 使用 npm
運行每一個包下面的 [script]
參考:
單個包的 node
項目能夠參考個人項目:sclean
單個包的前端項目能夠參考個人項目:see-fetch
多個包的項目能夠參考個人項目:lila
更多博客,查看 https://github.com/senntyou/blogs
版權聲明:自由轉載-非商用-非衍生-保持署名(創意共享3.0許可證)