前端架構之路(6)
元件化
1. 什麼是 “元件化”
元件化就是將專案中可以共用的程式碼提取出來,單獨成一個元件,以便在多個地方呼叫此元件,這樣便可以做到只維護一份程式碼,而不需要每次更新都要改多個地方,而且還不能保證都一樣。
元件化一般分為專案內的元件化和專案外的元件化。
2. 專案內元件化
專案內的元件化,就是一個專案中可以共用的程式碼提取出來,獨立成元件,供專案其他地方呼叫。比如像上一節推薦使用的目錄結構中的 component
目錄:
|-- project/ 工程目錄
|-- src/ 原始碼目錄
|-- component/ 全域性元件目錄
|-- util/ 全域性工具函式目錄
|-- ...
專案內的元件化對於單個專案是很適用,但當元件需要被跨專案使用(多個專案同時使用)時,便有些棘手了。
3. 徹底元件化
徹底元件化就是將元件獨立成一個專案,如果需要在其他專案使用這個元件,就需要依賴這個專案。這個時候,元件化一般都是搭配版本管理工具和版本管理系統一起使用。
版本管理系統以 gitlab 為例進行說明。
3.1 目錄結構示例
|-- project1/ 專案1
|-- package.json
|-- .gitignore
|-- README.md
|-- lila.config.js
|-- ...
|-- project/ 工程目錄
|-- src/ 原始碼目錄
|-- component/ 專案內元件目錄
|-- util/ 全域性工具函式目錄
|-- ...
|-- component1/ 元件1
|-- package.json
|-- .gitignore
|-- README.md
|-- webpack.config.js
|-- src/ 原始碼目錄
|-- ...
|-- component2/ 元件2
|-- package.json
|-- .gitignore
|-- README.md
|-- webpack.config.js
|-- src/ 原始碼目錄
|-- ...
3.2 使用元件
在 project1
中安裝 component1, component2
依賴。
# package.json
{
"dependencies": {
"component1": "git+http://yourGit.com/yourName/component1.git#0.0.1",
"component2": "git+http://yourGit.com/yourName/component2.git#0.0.1"
}
}
# code
// commonjs
const component1 = require('component1');
// es6
import component1 from 'component1';
一般來說,獨立化元件要有 私有包命名字首。
# package.json
{
"dependencies": {
"@yourCompany/component1": "git+http://yourGit.com/yourName/component1.git#0.0.1",
"@yourCompany/component2": "git+http://yourGit.com/yourName/component2.git#0.0.1"
}
}
# code
// commonjs
const component1 = require('@yourCompany/component1');
// es6
import component1 from '@yourCompany/component1';
獨立化元件與私有 npm 倉庫配合使用是最完美的,下一節 私有 npm 倉庫 將會講到。
# npm
$ npm config set registry http://your.company.npm.registry.com
# package.json
{
"dependencies": {
"@yourCompany/component1": "^0.0.1",
"@yourCompany/component2": "^0.0.1"
}
}
# code
// commonjs
const component1 = require('@yourCompany/component1');
// es6
import component1 from '@yourCompany/component1';
4. 使用構建工具
團隊開發元件化之後,就會有大量的元件產生。與諸多專案一樣,如何既能快速開發,又有規範可循,維護成本最小化,當然還是得用構建工具呀。
以 yume 構建工具為例進行說明。
4.1 安裝工具
npm install yume -g
4.2 新建專案
yume new yume-demo && cd yume-demo && npm install yume --save-dev
4.3 根據需要更新配置檔案
配置檔案在專案根目錄下 yume.config.js
中。
module.exports = {
// 模組定義
modules: {
index: {
js: 'src/index.js',
filename: 'demo',
library: 'Demo',
libraryTarget: "umd"
},
ui: {
html: 'ui/index.html',
js: 'ui/index.js'
},
demo: {
html: 'demo/index.html',
js: 'demo/index.js'
},
example: {
html: 'example/index.html',
js: 'example/index.js'
}
},
// 外部依賴包(不需要被打包進 dist 檔案中)
externals: {
jquery: {
commonjs: 'jquery',
amd: 'jquery',
commonjs2: 'jquery',
root: 'jQuery'
},
...
},
// 單獨打包 css
packCssSeparately: true,
...
};
4.4 開發專案
yume dev moduleName
4.5 打包專案
yume dist moduleName
這個時候,會在 dist
目錄中生成相應的包檔案,然後執行 npm publish
就可以釋出到遠端倉庫中了。
5. 動態開發元件
元件開發中有一個比較突出的問題,就是很多元件往往是與實際專案有強依賴性,需要與實際專案進行實時除錯,而實際專案又是以版本化在管理元件,不能做到實時更新元件程式碼,元件必須釋出一個版本,實際專案才能更新,這極大的降低了開發效率和便利性。
解決這個問題當然還是需要構建工具的支援。以 lila 與 yume 為例進行說明:
目錄結構是這樣的
|-- projects/
|-- project1/ 專案1
|-- project2/ 專案2
|-- component1/ 元件1
|-- component2/ 元件2
在 project1
中程式碼是這樣的
# package.json
{
"dependencies": {
"@yourCompany/component1": "^0.0.1"
}
}
# code
require('@yourCompany/component1/dist/component1.css'); // css 檔案
const component1 = require('@yourCompany/component1'); // 主檔案
配置 lila.config.js
,讓專案支援動態載入 @yourCompany/component1
的開發程式碼
module.exports = {
...,
// 新增一個 `resolve.modules`(新增一個 webpack 載入包基地址)
resolveModules: [
'../'
],
// 別名配置(只有當命令列中有 `-o|out` 引數時才生效)
outResolveAlias: {
'@yourCompany/component1/dist/component1.css': 'component1/dist/component1.css',
'@yourCompany/component1': 'component1/dist/component1.js'
}
}
dev, dist @yourCompany/component1
元件的本地開發程式碼
執行 dev, dist, sync
命令時加上 -o, --out
引數,就可以載入 @yourCompany/component1
元件的本地開發程式碼
# dev
$ lila dev moduleName -o
# 正常執行,載入 0.0.1 版本中的程式碼
$ lila dev moduleName
# dist
$ lila dist moduleName -e 1 -out
# sync
$ lila sync moduleName -e 2 --out