ant-design-pro 使用總結—自定義打包 構建配置
ant-design-pro使用了umi.js,沒有直接使用webpack,我們要配置自定義的構建打包跟直接的webpack配置不太一樣。
首先,大部分的webpack打包配置都可以直接修改config/config.js來實現,比如 proxy,publicPath等。參考umi.js配置文件。https://umijs.org/zh/config/#基本配置。
這裡記錄一些針對性的配置。
hash配置。如何配置 umi.js,umi.css不使用hash檔名,其他非同步載入的檔案使用hash檔名?
我們的編譯生成的index.html檔案交給了後端,index.html上引用的umi.js,umi.css的版本號給後端控制,其他靜態資原始檔如js,css,圖片則放到cdn伺服器上,所以其他檔案則通過hash檔名來控制版本號。umi預設配置hash要麼是true要麼是false,不能滿足我們的需求。
怎麼辦?觀察發現打包構建生成的檔名是4.64e1afbe.chunk.css,4.6cf0f5d2.async.js這種格式,在node_modules中搜索.async.js,發現相關配置在node_modules/af-webpack下,程式碼如下:
if (opts.hash) {
webpackConfig.output.filename(`[name].[chunkhash:8].js`).chunkFilename(`[name].[chunkhash:8].async.js`);
}
const hash = !isDev && opts.hash ? '.[contenthash:8]' : ''; webpackConfig.plugin('extract-css').use(require('mini-css-extract-plugin'), [{ filename: `[name]${hash}.css`, chunkFilename: `[name]${hash}.chunk.css` }]);
手動修改對應內容,發現配置生效。但是我們不能直接個性它,而是要用外部配置來覆蓋它。
config/config.js 中有一個屬性 chainWebpack,使用了webpack-chain,詳細配置在config/plugin.config.js。
webpack-chain 配置文件: https://github.com/neutrinojs/webpack-chain/tree/v4
於是我們在config/plugin.config.js中新增程式碼:
//css的修改 config.plugin('extract-css').use(require('mini-css-extract-plugin'), [ { filename: `[name].css`, chunkFilename: `[name].[contenthash:8].chunk.css`, }, ]); //js的修改 config.output.filename('[name].js');
編譯,成功。
第三方元件src/lib資料夾的處理。禁用css modules編譯以及babel編譯處理。
實際開發中,不是所有的依賴都會放到 node_modules中,特別是一些我們自定義修改過的依賴,在 src/lib資料夾下放置這些特殊的依賴元件。元件放在這個資料夾下的表現並不跟放到node_modules中一樣,很多的原生構建打包配置都對node_modules作了排除處理,主要是css modules和babel編譯的時候,src/lib資料夾也需要做對應處理。
css modules
ant-design-pro預設開啟了css modules。
如果css modules作用範圍不排除src/lib資料夾,會導致引入元件的樣式錯亂。
檢視config/config.js發現cssLoaderOptions中有個getLocalIdent方法,用來生成css modules最終的class名。有下面幾行程式碼:
if (
context.resourcePath.includes('node_modules') ||
context.resourcePath.includes('ant.design.pro.less') ||
context.resourcePath.includes('global.less')
) {
return localName;
}
可以看出,node_modules,ant.design.pro.less,global.less 這幾種檔案下 css modules 使用原始的css class名稱,相當於是把這些檔案排除在css modules作用範圍之外了。於是我們要排除src/lib資料夾,只需要在這個函式中加一行:
if (
context.resourcePath.includes('node_modules') ||
context.resourcePath.includes('ant.design.pro.less') ||
context.resourcePath.includes('global.less')||
context.resourcePath.includes('/src/lib/')
) {
return localName;
}
babel排除
引用src/lib下部分es5寫的元件的時候,發現執行報錯:
TypeError: 'caller', 'callee', and 'arguments' properties may not be accessed on strict mode functions or the arguments objects for calls to them
因為babel轉譯的時候貌似預設都轉成嚴格模式了。本來只需要exclude一下這些元件的,但是umi的配置裡並沒有找到相關的項。同樣,我們在node_modules/af-webpack下搜尋babel相關配置。搜到如下程式碼:
webpackConfig.module
.rule('js')
.test(/\.js$/)
.include.add(opts.cwd)
.end()
.exclude.add(/node_modules/)
.end()
.use('babel-loader')
.loader(require.resolve('babel-loader'))
.options(babelOpts); // module -> jsx
對應的,我們在config/plugin.config.js中新增下面的程式碼:
config.module
.rule('js')
.exclude.add(/\/src\/lib\/webuploader/)
.end();
搞定。