覆盖webpack配置
- react-app-rewired
-
prettier+eslint
安装
yarn add @typescript-eslint/parser @typescript-eslint/eslint-plugin eslint-plugin-react --dev
yarn add prettier eslint-config-prettier eslint-plugin-prettier --dev
配置
根目录下新建 .eslintrc.js
module.exports = {
env: {
browser: true,
node: true,
},
parser: "@typescript-eslint/parser", // 指定ESLint解析器
extends: [
"plugin:react/recommended", // 使用来自 @eslint-plugin-react 的推荐规则
"plugin:@typescript-eslint/recommended", // 使用来自@typescript-eslint/eslint-plugin的推荐规则
"prettier/@typescript-eslint", // 使用 ESLint -config-prettier 禁用来自@typescript-eslint/ ESLint 与 prettier 冲突的 ESLint 规则
"plugin:prettier/recommended",
],
parserOptions: {
ecmaVersion: 2018, // 允许解析最新的 ECMAScript 特性
sourceType: "module", // 允许使用 import
ecmaFeatures: {
jsx: true, // 允许对JSX进行解析
},
},
rules: {
// 自定义规则
"no-console": process.env.NODE_ENV === "production" ? "error" : "off",
"no-debugger": process.env.NODE_ENV === "production" ? "error" : "off",
endOfLine: 0,
"no-unused-vars": 0,
"no-useless-escape": 0, //忽略转义字符验证
},
settings: {
react: {
version: "detect", // 告诉 eslint-plugin-react 自动检测 React 的版本
},
},
globals: {
AMap: true,
},
};
根目录新建 .prettierrc.js
module.exports = {
eslintIntegration: true,
singleQuote: false,
semi: true,
printWidth: 200,
};
根目录新建 .vscode
文件夹,下新建 setting.json
{
"files.autoSave": "onFocusChange",
"editor.formatOnSave": true,
"editor.formatOnType": true,
"eslint.autoFixOnSave": true,
"eslint.enable": true
}
DLL
前段时间,写了一篇关于vue-cli3 的 Dllplugin 链接,个人项目是react的,所以也想修改一下。代码大部分都是一样的。提倡不要改默认配置,就是不建议要npm run eject
。可以类似vue.config.js一样新建文件配置最后覆盖。其实antd ui 按需加载就提供了一个思路 customize-cra
。
在上面也是可以写配置文件。我以配置dllplugin为例。到时候可以自己按照实际项目扩展。
当前文件目录新建 webpack.dll.config.js
const path = require('path')
const webpack = require('webpack')
const {
CleanWebpackPlugin
} = require('clean-webpack-plugin')
// dll文件存放的目录
const dllPath = 'public/vendor'
module.exports = {
entry: {
// 需要提取的库文件
vendor: ['react','antd','react-dom','react-redux','redux','react-router-dom','redux-thunk','axios','less-loader']
},
output: {
path: path.join(__dirname, dllPath),
filename: '[name].dll.js',
// vendor.dll.js中暴露出的全局变量名
// 保持与 webpack.DllPlugin 中名称一致
library: '[name]_[hash]'
},
plugins: [
// 清除之前的dll文件
new CleanWebpackPlugin(),
// 设置环境变量
new webpack.DefinePlugin({
'process.env': {
NODE_ENV: 'production'
}
}),
// manifest.json 描述动态链接库包含了哪些内容
new webpack.DllPlugin({
path: path.join(__dirname, dllPath, '[name]-manifest.json'),
// 保持与 output.library 中名称一致
name: '[name]_[hash]',
context: process.cwd()
})
]
}
package.json
"scripts": {
"start": "react-app-rewired start",
+ "dll": "webpack -p --progress --config ./webpack.dll.conf.js",
"build": "react-app-rewired build",
"test": "react-app-rewired test"
},
npm run dll
在public文件夹下面生成vendor文件即可
完整配置
config-overrides.js (可以去看antd UI 官网按需加载 地址链接)。这里只是在基础上扩张webpack配置addCustomize
。
const {
override,
addLessLoader,
fixBabelImports,
addWebpackAlias,
addDecoratorsLegacy,
overrideDevServer,
} = require("customize-cra");
const path = require("path");
const webpack = require("webpack");
const AddAssetHtmlPlugin = require("add-asset-html-webpack-plugin");
/**
* 打包进度条
*/
const WebpackBar = require("webpackbar");
/**
* 生产环境去除注释
*/
const TerserPlugin = require("terser-webpack-plugin");
/**
* webpack 打包分析
*
*/
const { BundleAnalyzerPlugin } = require("webpack-bundle-analyzer"); //分析插件,打包后在build/static/report.html中展示各模块所占的大小
/**
* 速度分析
*/
const SpeedMeasurePlugin = require("speed-measure-webpack-plugin");
const smp = new SpeedMeasurePlugin();
/**
* 开启gzip压缩
*/
const productionGzipExtensions = ["js", "css", "json", "txt"];
const CompressionWebpackPlugin = require("compression-webpack-plugin");
/**
*
* 环境变量
*
*/
const ENV = process.env;
/**
* 开发服务配置
*/
const devServerConfig = () => (config) => {
console.log("=======>" + config.mode + "===========");
config.proxy = {
"/api": {
target: ENV.REACT_APP_BASE_URL,
changeOrigin: true,
logLevel: "debug",
secure: false,
},
};
return config;
};
/**
*
* webpack-config配置
*
*/
const rewiredMap = () => (config) => {
// config为所有的webpack配置
config.devtool =
config.mode === "development" ? "cheap-module-source-map" : false; // 生产环境关闭sourcemap关闭
config.plugins.push(new WebpackBar());
if (config.mode === "production") {
config.plugins.push(
new CompressionWebpackPlugin({
test: new RegExp("\\.(" + productionGzipExtensions.join("|") + ")$"),
threshold: 10240, // 对超过10k的数据压缩
deleteOriginalAssets: false, // 不删除源文件
}),
new TerserPlugin({
extractComments: true,
cache: true,
parallel: true,
sourceMap: true, // Must be set to true if using source-maps in production
terserOptions: {
extractComments: "all",
compress: {
drop_console: true,
},
},
}),
new webpack.optimize.SplitChunksPlugin({
chunks: "all",
minSize: 20000,
minChunks: 1,
maxAsyncRequests: 5,
maxInitialRequests: 3,
name: true,
})
);
}
return config;
};
/**
* dll配置,不建议生产环境使用 ,不常变化的包使用dll加快打包速度
*/
const addCustomize = () => (config) => {
if (config.mode === "development") {
config.plugins.push(
new webpack.DllReferencePlugin({
context: process.cwd(),
manifest: require("./public/vendor/vendor-manifest.json"),
}),
// 将 dll 注入到 生成的 html 模板中
new AddAssetHtmlPlugin({
// dll文件位置
filepath: path.resolve(__dirname, "./public/vendor/*.js"),
// dll 引用路径
publicPath: "./vendor",
// dll最终输出的目录
outputPath: "./vendor",
})
);
}
return config;
};
/**
* 打包分析
*/
const analyzerConfig = () => (config) => {
if (config.mode === "production") {
config.plugins.push(
new BundleAnalyzerPlugin({
analyzerMode: "static", //输出静态报告文件report.html,而不是启动一个web服务
})
);
}
return config;
};
const webpackConfig = override(
fixBabelImports("import", {
libraryName: "antd",
libraryDirectory: "es",
style: "css",
}),
addLessLoader({
lessOptions: {
javascriptEnabled: true,
localIdentName: "[local]--[hash:base64:5]",
},
}),
addWebpackAlias({
"@": path.resolve(__dirname, "./src"),
}),
(config, env) => {
//修改、添加loader 配置 :
// 所有的loaders规则是在config.module.rules(数组)的第二项
// 即:config.module.rules[2].oneof (如果不是,具体可以打印 一下是第几项目)
// 修改 less 配置 ,规则 loader 在第7项(具体可以打印配置)
const loaders = config.module.rules.find((rule) =>
Array.isArray(rule.oneOf)
).oneOf;
loaders[7].use.push({
loader: "style-resources-loader",
options: {
patterns: [
path.resolve(__dirname, "src/styles/mixin.less"),
path.resolve(__dirname, "src/styles/variables.less"),
],
},
});
return config;
},
addDecoratorsLegacy(),
rewiredMap(),
// addCustomize(),
analyzerConfig()
);
module.exports = {
webpack: webpackConfig,
devServer: overrideDevServer(devServerConfig()),
};
npm run build
看能不能在打包后的文件夹中index.html中是否引用vendor文件,成功就ok了。跟vue-cli3相似。
{
"name": "react_antd_admin_template",
"version": "1.0.0",
"author": "wangchaoxu",
"license": "MIT",
"private": true,
"scripts": {
"start": "cross-env react-app-rewired start",
"serve": "react-app-rewired start",
"build": "cross-env react-app-rewired --max-old-space-size=4096 build ",
"clear": "rimraf node_modules && rimraf yarn.lock",
"test": "react-app-rewired test",
"eject": "react-scripts eject",
"commit": "git cz",
"dll2": "webpack -p --progress --config webpack.dll.config.js",
"dll": "webpack --config webpack.dll.config.js"
},
"dependencies": {
"@testing-library/jest-dom": "^4.2.4",
"@testing-library/react": "^9.5.0",
"@testing-library/user-event": "^7.2.1",
"@toast-ui/react-editor": "^2.1.0",
"antd": "^3.17.0",
"axios": "^0.19.2",
"cross-env": "^7.0.3",
"driver.js": "^0.9.8",
"echarts": "^4.7.0",
"js-cookie": "^2.2.1",
"less": "^3.9.0",
"less-loader": "5.0.0",
"lodash-es": "^4.17.20",
"nprogress": "^0.2.0",
"prop-types": "^15.7.2",
"react": "^16.13.1",
"react-beautiful-dnd": "^13.0.0",
"react-countup": "^4.3.3",
"react-custom-scrollbars": "^4.2.1",
"react-document-title": "^2.0.3",
"react-dom": "^16.13.1",
"react-draft-wysiwyg": "^1.14.5",
"react-loadable": "^5.5.0",
"react-redux": "^7.2.0",
"react-router-dom": "^5.1.2",
"react-scripts": "3.4.1",
"redux": "^4.0.5",
"redux-thunk": "^2.3.0",
"script-loader": "^0.7.2"
},
"browserslist": {
"production": [
">0.2%",
"not dead",
"not op_mini all"
],
"development": [
"last 1 chrome version",
"last 1 firefox version",
"last 1 safari version"
]
},
"devDependencies": {
"@babel/plugin-proposal-decorators": "^7.12.12",
"add-asset-html-webpack-plugin": "^3.1.3",
"babel-plugin-import": "^1.13.0",
"clean-webpack-plugin": "^3.0.0",
"commitizen": "^4.0.3",
"compression-webpack-plugin": "6.1.1",
"customize-cra": "^1.0.0",
"cz-conventional-changelog": "^3.0.2",
"less": "^4.0.0",
"less-loader": "^7.2.1",
"mockjs": "^1.1.0",
"react-app-rewire-css-modules": "^1.0.0",
"react-app-rewire-less-modules": "^1.3.0",
"react-app-rewired": "^2.1.5",
"speed-measure-webpack-plugin": "^1.3.3",
"style-resources-loader": "^1.4.1",
"styled-components": "^5.2.1",
"terser-webpack-plugin": "3.1.0",
"user-agent": "^1.0.4",
"webpack-bundle-analyzer": "^4.3.0",
"webpack-cli": "3.3.12",
"webpackbar": "^5.0.0-3"
},
"config": {
"commitizen": {
"path": "./node_modules/cz-conventional-changelog"
}
}
}