ant-design-pro使用了umi.js,没有直接使用webpack,我们要配置自定义的构建打包跟直接的webpack配置不太一样。
首先,大部分的webpack打包配置都可以直接修改config/config.js来实现,比如 proxy,publicPath等。参考umi.js配置文档。https://umijs.org/zh/config/#基本配置。
这里记录一些针对性的配置。
我们的编译生成的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');
编译,成功。
实际开发中,不是所有的依赖都会放到 node_modules中,特别是一些我们自定义修改过的依赖,在 src/lib文件夹下放置这些特殊的依赖组件。组件放在这个文件夹下的表现并不跟放到node_modules中一样,很多的原生构建打包配置都对node_modules作了排除处理,主要是css modules和babel编译的时候,src/lib文件夹也需要做对应处理。
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;
}
引用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();
搞定。
github 地址:https://github.com/liusaint/ls-blog/issues/32