背景:本篇博客针对React项目的一些配置:
在react项目中使用'@'代替src路径
打包上线后去除控制台console.log() ,路由懒加载 ,CDN等优化
redux使用
1. 用craco来配置路径别名'@'
在React脚手架项目中:
CRA(create-react-app) 将所有工程化配置,都隐藏在了 react-scripts
包中,所以,项目中看不到任何配置信息或者是配置文件。
如果要修改 CRA 的默认配置,有以下几种方案:
- 【推荐】通过第三方库来修改,比如,
@craco/craco
- 通过执行
yarn eject
命令,释放react-scripts
中的所有配置到项目中(注意:该操作不可逆!!!)
1.craco:
craco是对create-react-app
进行自定义配置的一款工具。
2.craco的使用步骤
-
安装包。
npm i -D @craco/craco
-
在项目根目录下,创建配置文件:
craco.config.js
。在配置文件中就可以做自定义的修改了。craco.config.js
中配置路径别名:
const path = require('path')
module.exports = {
webpack: {
alias: {
'@': path.join(__dirname, 'src')
}
}
}
复制代码
3.修改 package.json
中的脚本命令
package.json 中:
// 将 start/build/test 三个命令修改为 craco 方式
"scripts": {
"start": "craco start",
"build": "craco build",
"test": "craco test",
"eject": "react-scripts eject"
}
复制代码
- 在代码中,就可以通过
@
来表示 src 目录的绝对路径 - 重启项目,让配置生效
2.vscode识别@并提示路径
vscode打开配置过craco的react项目中不会对@路径提示,需要在根目录下配置jsconfig.json
文件:
// VSCode 会自动读取 `jsconfig.json` 中的配置,让 vscode 知道 @ 就是 src 目录
{
"compilerOptions": {
"baseUrl": "./",
"paths": {
"@/*": ["src/*"]
}
}
}
复制代码
3.React项目打包和优化
1.项目打包:
- 在项目根目录打开终端,输入打包命令:
npm run build
(实际命令需查看package.json文件) - 等待打包完成,打包后的内容被放在项目根下的 build 文件夹中
2.项目预览:
- 全局安装本地服务包:
npm i -g serve
,该包提供了serve
命令,用来启动本地服务 - 在项目根目录中执行命令:
serve -s ./build
,在 build 目录中开启服务器 - 在浏览器中 预览项目
3.打包体积分析
通过分析打包体积,才能知道项目中的哪部分内容体积过大,才能知道如何来优化
- 安装分析打包体积的包:
npm i source-map-explorer
- 在 package.json 中的 scripts 标签中,添加分析打包体积的命令:
"scripts": {
"analyze": "source-map-explorer 'build/static/js/*.js'",
}
复制代码
- 对项目打包:
npm run build
(如果已经打过包,可省略这一步) - 运行分析命令:
npm run analyze
- 通过浏览器打开的页面,分析图表中的包体积
4.生产环境优化
根据是否为生产环境对redux中的thunk
中间件进行优化,
有关redux
和thunk
中间件,请参考React中redux的使用
let middlewares
if (process.env.NODE_ENV === 'production') {
// 生产环境,只启用 thunk 中间件
middlewares = applyMiddleware(thunk)
} else {
middlewares = composeWithDevTools(applyMiddleware(thunk))
}
复制代码
5.路由懒加载
- 在
App
根组件中,导入Suspense
组件 - 在
Router
内部,使用Suspense
组件包裹组件内容 - 为
Suspense
组件提供fallback
属性,指定 loading 占位内容(加载缓慢是页面显示的内容) - 导入
lazy
函数,并修改为懒加载方式导入路由组件
// 导入lazy 和 Suspense组件
import { lazy, Suspense } from 'react'
// lazy导入页面组件
const Login = lazy(() => import('./pages/Login'))
const Layout = lazy(() => import('./pages/Layout'))
const App = () => {
return (
<Router>
<Suspense
fallback={
<div
style={{
textAlign: 'center',
marginTop: 200
}}
>
loading... // fallback属性配置的加载时显示的内容
</div>
}
>
<div className="app">
<Route path="/login" component={Login}></Route>
<Route path="/home" component={Layout}></Route>
</div>
</Suspense>
</Router>
)
}
export default App
复制代码
6.去除控制台console
这里借助terser-webpack-plugin
包实现去除console.log()一下是webpack关于terser-webpack-plugin
的描述:
webpack v5 开箱即带有最新版本的
terser-webpack-plugin
。如果你使用的是 webpack v5 或更高版本,同时希望自定义配置,那么仍需要安装terser-webpack-plugin
。如果使用 webpack v4,则必须安装terser-webpack-plugin
v4 的版本。
注意 : 配置之前需要确实使用的webpack是哪个版本,安装对应的版本包:
npm i [email protected]
在craco.config.js
的文件中配置如下(craco.config.js
文件在上面配置了craco):
const path = require('path')
const TerserPlugin = require('terser-webpack-plugin')
module.exports = {
webpack: {
// 配置识别 @ 路径
alias: {
'@': path.join(__dirname, 'src')
},
plugins: [
new TerserPlugin({
terserOptions: {
compress: {
drop_console: process.env.NODE_ENV === 'production'
// 生产环境下移除控制台所有的内容
}
}
})
]
}
}
复制代码
7.配置CDN
完整craco.js
文件
const path = require('path')
const TerserPlugin = require('terser-webpack-plugin')
const { whenProd, getPlugin, pluginByName } = require('@craco/craco')
module.exports = {
webpack: {
// 识别@
alias: {
'@': path.join(__dirname, 'src')
},
// 移出console.log()
plugins: [
new TerserPlugin({
terserOptions: {
compress: {
drop_console: process.env.NODE_ENV === 'production'
// 生产环境下移除控制台所有的内容
}
}
})
],
// CDN
configure: (webpackConfig) => {
let cdn = {
js: [],
css: []
}
// 对webpack进行配置
whenProd(() => {
// 只会在生产环境执行
webpackConfig.externals = {
react: 'React',
'react-dom': 'ReactDOM',
redux: 'Redux'
}
cdn = {
js: [
'https://cdn.bootcdn.net/ajax/libs/react/17.0.2/umd/react.production.min.js',
'https://cdn.bootcdn.net/ajax/libs/react-dom/17.0.2/umd/react-dom.production.min.js',
'https://cdn.bootcdn.net/ajax/libs/redux/4.1.0/redux.min.js'
],
css: []
}
})
const { isFound, match } = getPlugin(
webpackConfig,
pluginByName('HtmlWebpackPlugin')
)
if (isFound) {
// 找到了html的插件
match.options.cdn = cdn
}
return webpackConfig
}
}
}
复制代码
在public文件夹中index.html
中引入相应文件
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<link rel="icon" href="%PUBLIC_URL%/favicon.ico" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<meta name="theme-color" content="#000000" />
<meta
name="description"
content="Web site created using create-react-app"
/>
<link rel="apple-touch-icon" href="%PUBLIC_URL%/logo192.png" />
<link rel="manifest" href="%PUBLIC_URL%/manifest.json" />
<title>React App</title>
<% htmlWebpackPlugin.options.cdn.css.forEach(cdnURL => { %>
<link rel="stylesheet" href="<%= cdnURL %>"></link>
<% }) %>
</head>
<body>
<noscript>You need to enable JavaScript to run this app.</noscript>
<div id="root"></div>
<% htmlWebpackPlugin.options.cdn.js.forEach(cdnURL => { %>
<script src="<%= cdnURL %>"></script>
<% }) %>
</body>
</html>
复制代码