早些时候CRA(create-react-app)升级到2.0.3的时候, react-app-rewired没有跟着升级, 导致项目无法启动, 于是乎直接eject 开始改造项目.
查看版本
> create-react-app --version
2.0.3
创建项目
create-react-app my-project
cd my-project
yarn eject # 输入 y
目前为止项目目录结构, 忽略node_modules这个黑洞
├── README.md
├── config
│ ├── env.js
│ ├── jest
│ │ ├── cssTransform.js
│ │ └── fileTransform.js
│ ├── paths.js
│ ├── webpack.config.js
│ └── webpackDevServer.config.js
├── package.json
├── public
│ ├── favicon.ico
│ ├── index.html
│ └── manifest.json
├── scripts
│ ├── build.js
│ ├── start.js
│ └── test.js
├── src
│ ├── App.css
│ ├── App.js
│ ├── App.test.js
│ ├── index.css
│ ├── index.js
│ ├── logo.svg
│ └── serviceWorker.js
└── yarn.lock
安装依赖
yarn add antd
yarn add babel-plugin-import less less-loader @babel/plugin-proposal-decorators -D
CRA eject之后package.json里面没有区分devDependencies 和 dependencies, 但是不影响使用
因为antd是使用的less, CRA默认不支持, 所以需要改下默认的webpack配置, config/webpack.config.js
首先修改babel配置
个人习惯使用babelrc, 所以把babel-loader options中babelrc的值改为true, 增加.babelrc文件
{
"presets": [
"react-app"
],
"plugins": [
[
"import",
{
"libraryName": "antd",
"libraryDirectory": "lib",
"style": true
},
"ant"
],
[
"@babel/plugin-proposal-decorators", // 启用装饰器
{
"legacy": true
}
]
]
}
参照默认的sass配置, 增加less配置
const sassRegex = /\.(scss|sass)$/;
const sassModuleRegex = /\.module\.(scss|sass)$/;
const lessRegex = /\.less$/;
const lessModuleRegex = /\.module\.less$/;
在module>rules中添加规则
// sass rule
//...
{
test: lessRegex,
exclude: lessModuleRegex,
use: getStyleLoaders(
{
importLoaders: 2,
sourceMap: isEnvProduction && shouldUseSourceMap
},
'less-loader',
{
javascriptEnabled: true
}
),
sideEffects: true
},
{
test: lessModuleRegex,
use: getStyleLoaders(
{
importLoaders: 2,
sourceMap: isEnvProduction && shouldUseSourceMap,
modules: true,
getLocalIdent: getCSSModuleLocalIdent
},
'less-loader',
{
javascriptEnabled: true
}
)
}
// file loader
至此基本项目虽然已经基本完成, 但是如果你是使用less版本比较高, 项目是无法运行的
参考issue
需要改造getStyleLoaders函数, 增加第三个参数otherConfig, 就是上面代码中的 javascriptEnabled: true
const getStyleLoaders = (cssOptions, preProcessor, otherConfig) => {
const loaders = [
isEnvDevelopment && require.resolve('style-loader'),
isEnvProduction && {
loader: MiniCssExtractPlugin.loader,
options: Object.assign({}, shouldUseRelativeAssetPaths ? { publicPath: '../../' } : undefined)
},
{
loader: require.resolve('css-loader'),
options: cssOptions
},
{
loader: require.resolve('postcss-loader'),
options: {
ident: 'postcss',
plugins: () => [
require('postcss-flexbugs-fixes'),
require('postcss-preset-env')({
autoprefixer: {
flexbox: 'no-2009'
},
stage: 3
})
],
sourceMap: isEnvProduction && shouldUseSourceMap
}
}
].filter(Boolean);
if (preProcessor) {
loaders.push({
loader: require.resolve(preProcessor),
options: {
sourceMap: isEnvProduction && shouldUseSourceMap,
...otherConfig
}
});
}
return loaders;
};
这样修改之后, 自定义主题modifyVars也可以写在otherConfig中, 一举两得, 不多赘述.
至此项目
优化完善, 启用dll
关于dll的利弊不再赘述, 这里只是说明我用的方法, 也不详细展开, 每个人的项目可能都不一样
安装插件
yarn add clean-webpack-plugin webpack-cli add-asset-html-webpack-plugin -D
在config/paths.js exports对象中增加一行kv
appDll: resolveApp("dll"),
增加config/webpack.dll.conf.js文件
const paths = require('./paths');
const path = require('path');
const webpack = require('webpack');
const CleanWebpackPlugin = require('clean-webpack-plugin');
const vendors = [
'react',
'react-dom'
];
module.exports = {
mode: 'production',
performance: {
hints: false
},
output: {
path: paths.appDll,
publicPath: paths.servedPath,
filename: '[name].[hash].dll.js',
library: '[name]_[hash]'
},
entry: {
vendor: vendors
},
plugins: [
new CleanWebpackPlugin([paths.appDll], {
root: paths.appPath, // 根目录
verbose: true, // 开启在控制台输出信息
dry: false // 启用删除文件
}),
new webpack.IgnorePlugin(/^\.\/locale$/, /moment$/),
new webpack.DllPlugin({
path: path.join(paths.appDll, '[name]-manifest.json'),
name: '[name]_[hash]'
})
]
};
package.json增加dll 脚本
"dll": "webpack --progress --config config/webpack.dll.conf.js"
运行 yarn dll
打包vendor在dll文件夹中
生产模式使用dll, 修改webpack.conf.js, 增加assets插件和dllreference插件
...
const AddAssetHtmlPlugin = require("add-asset-html-webpack-plugin");
....
plugins: {
...
...
isEnvProduction &&
new webpack.DllReferencePlugin({
manifest: require('../dll/vendor-manifest.json')
}),
isEnvProduction &&
new AddAssetHtmlPlugin({
filepath: path.resolve(paths.appDll, '*.js'),
includeSourcemap: false
}),
}
至此结束, 验证效果
yarn build
build 文件夹结构
├── asset-manifest.json
├── favicon.ico
├── index.html
├── manifest.json
├── precache-manifest.8175e98134227f2327b88338d3024239.js
├── service-worker.js
├── static
│ ├── css
│ │ ├── 1.83e366fa.chunk.css
│ │ ├── 1.83e366fa.chunk.css.map
│ │ ├── main.c7ff46e9.chunk.css
│ │ └── main.c7ff46e9.chunk.css.map
│ ├── js
│ │ ├── 1.860809fa.chunk.js
│ │ ├── 1.860809fa.chunk.js.map
│ │ ├── main.0df678d7.chunk.js
│ │ ├── main.0df678d7.chunk.js.map
│ │ ├── runtime~main.229c360f.js
│ │ └── runtime~main.229c360f.js.map
│ └── media
│ └── logo.5d5d9eef.svg
└── vendor.52ec4f1c0bead1c1a489.dll.js
本地运行serve -s build
, 项目能正常显示, build文件夹下有vendor.hash.dll.js则说明配置成.