(转)cube-ui后编译
轉(zhuǎn)載地址:https://www.jianshu.com/p/189755f9ce43
1. 后編譯介紹
目前大部分的前端項目開發(fā)都是使用es6+的代碼并且使用babel進(jìn)行編譯,而傳統(tǒng)的對代碼包的引入都是引入一個被babel編譯好的文件入口,這樣帶來了一個缺點,那就是項目中無用的代碼也會被引入到最終打包的文件中。
后編譯的思想是不會在包發(fā)布的時候進(jìn)行編譯,而是會在使用這個包的前端項目構(gòu)建的時候進(jìn)行編譯。
下面就來看一下cube-ui對更好的使用后編譯作出的探索。
2. 后編譯遇到的問題
2.1 后編譯和普通編譯的兼容
由于webpack的開發(fā)團(tuán)隊也考慮到直接引入一個編譯好的代碼包帶來的一些問題,所以在webpack2.x之后引入了一個屬性。
module.exports = {
// ...
resolve: {
mainFields: ["browser", "module", "main"]
}
// ...
}
在引入一個第三方包的時候,會根據(jù)mainFields的隊列頭到隊列尾的順序檢測package.json文件中是否有這些字段值。
上面的示例代碼是target值為webworker時的默認(rèn)配置,當(dāng)target為其他值時,mainFields的默認(rèn)值為:
mainFields: ["module", "main"]
在使用cube-ui時我們?nèi)绾闻渲檬褂煤缶幾g或者時普通編譯呢?
后編譯時直接引入代碼包時就會默認(rèn)引入ES2015 module的代碼,對于普通編譯需要在webpack.base.conf.js中配置別名解析。
module.exports = {
// ...
resolve: {
alias: {
// ...
"cube-ui": "cube-ui/lib"
}
}
// ...
}
這樣在引入時就可以引入到編譯后的代碼。
2.2 引入路徑
在做到上面的幾步后,就可以實現(xiàn)代碼包的后編譯,但是這里有一個引入路徑的問題。比如我們要引入cube-ui的switch組件,我們需要這樣引入:
import Switch from 'cube-ui/src/modules/switch'
這樣的引入方式對于用戶來說肯定不是很友好。
通過cube-ui團(tuán)隊開發(fā)的webpack插件webpack-transform-modules-plugin可以通過下面的方式進(jìn)行組件的引入。
import {Switch} from 'cube-ui'
在引入這個插件的同時需要在package.json中引入下面的代碼:
{
// ...
"transformModules": {
"cube-ui": {
"transform": "cube-ui/src/modules/${member}",
"kebabCase": true
}
},
// ...
}
通過這段配置來解析cube-ui的引入路徑。
同時還要在webpack.base.conf.js中添加webpack-transform-modules-plugin插件。
var PostCompilePlugin = require('webpack-post-compile-plugin')
var TransformModulesPlugin = require('webpack-transform-modules-plugin')
module.exports = {
// ...
plugins: [
// ...
new PostCompilePlugin(),
new TransformModulesPlugin()
]
// ...
}
2.3 嵌套后編譯
如果我們要使用后編譯還要在webpack配置的rules中加入include配置,比如要后編譯代碼包A和B,就要寫下面的代碼:
module.exports = {
// ...
module: {
rules: [
// ...
{
test: /.js$/,
loader: 'babel-loader',
// 注意這里的 include
// 除了 src 還包含了額外的 node_modules 下的兩個包
include: [
resolve('src'),
resolve('node_modules/A'),
resolve('node_modules/B')
]
},
// ...
]
},
// ...
}
如果在后編譯的生態(tài)中,會出現(xiàn)下面的情況:
這里借用cube-ui團(tuán)隊的一張嵌套后編譯的圖。
當(dāng)A為后編譯,A依賴的包C和D也為后編譯時,需要在應(yīng)用的webpack配置中增加rules.include的配置:
module.exports = {
// ...
module: {
rules: [
// ...
{
test: /.js$/,
loader: 'babel-loader',
// 注意這里的 include
// 除了 src 還包含了額外的 node_modules 下的兩個包
include: [
resolve('src'),
resolve('node_modules/A'),
resolve('node_modules/B'),
resolve('node_modules/C'),
resolve('node_modules/D')
]
},
// ...
]
},
// ...
}
cube-ui團(tuán)隊為了解決這種情況開發(fā)了webpack插件webpack-post-compile-plugin,通過這個插件可以通過獲取package.json文件中的compileDependencies屬性來獲取當(dāng)前包依賴的后編譯包,并且將這些包添加到webpack配置的rules.include中。
webpack-post-compile-plugin插件的核心代碼如下:
PostCompilePlugin.prototype.apply = function (compiler) {
var that = this
compiler.plugin(['before-run', 'watch-run'], function (compiler, callback) {
// ...
var dependencies = that._collectCompileDependencies(compiler)
if (dependencies.length) {
var rules = compiler.options.module.rules
rules && rules.forEach(function (rule) {
if (rule.include) {
if (!Array.isArray(rule.include)) {
rule.include = [rule.include]
}
rule.include = rule.include.concat(dependencies)
}
})
}
callback()
})
}
就是在webpack編譯過程中的before-run和watch-run的兩個鉤子中進(jìn)行依賴的收集。
3. 使用后編譯的其他問題
由于cube-ui使用的是stylus進(jìn)行樣式的編寫,如果采用后編譯需要在前端工程中配置stylus的解析。
在vue-loader的配置中添加下面的配置。
const stylusOptions = {
'resolve url': true
}
return {
css: generateLoaders(),
postcss: generateLoaders(),
less: generateLoaders('less'),
sass: generateLoaders('sass', { indentedSyntax: true }),
scss: generateLoaders('sass'),
stylus: generateLoaders('stylus',stylusOptions),
styl: generateLoaders('stylus',stylusOptions)
}
總結(jié)
后編譯的優(yōu)點是能對依賴包中的代碼進(jìn)行依賴分析,從而讓公共的依賴被提取出來。由于后編譯是在前端應(yīng)用構(gòu)建時一起構(gòu)建,所以babel轉(zhuǎn)換的API只有一份,不會冗余。
缺點是包的babel配置要與應(yīng)用的babel配置兼容,依賴包不能使用alias和DefinePlugin。編譯時間會變長。
后編譯是一種生態(tài),如果你編寫的代碼包需要使用后編譯,那么就要遵守后編譯的配置規(guī)定。
作者:imamba
鏈接:https://www.jianshu.com/p/189755f9ce43
來源:簡書
簡書著作權(quán)歸作者所有,任何形式的轉(zhuǎn)載都請聯(lián)系作者獲得授權(quán)并注明出處。
總結(jié)
以上是生活随笔為你收集整理的(转)cube-ui后编译的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 少数民族都有哪些节日?
- 下一篇: 中秋针对新老客户的一些活动怎么推广效果好