一,配置基础代码
增加配置文件 webpack.base.js
module.exports = {
mode: 'development',
entry: path.resolve(__dirname, 'src', 'index.js'),
output: {
path: path.resolve(__dirname, 'dist'),
filename: 'bundle.js',
publicPath: '/',
clean: true,
},
plugins: [
new HtmlWebpackPlugin({
template: path.resolve(__dirname, './', 'index.html'),
filename: 'index.html',
hash: true,
}),
],
}
二,配置 JS Loader
module: {
rules: [
{
test: /\.m?js$/,
exclude: /node_modules/,
use: {
loader: "babel-loader",
options: {
presets: ["@babel/preset-env", "@babel/preset-react"]
}
}
},
]
}
三,第一次执行 Webpack
先新建一个组件
import React, { Suspense } from 'react';
import dayjs from 'dayjs';
function App() {
return <div>
Hello! {dayjs(new Date()).format('yyyy')}
</div>
}
执行编译
webpack —config=webpack.base.js
得到 bundle.js 但是发现 React,dayjs 库代码打包到一起了
四,分离库文件
把 output 中固定的 bundle.js 改为 [name].bundle.js 然后加入以下代码
optimization: {
splitChunks: {
chunks: 'all',
},
},
编译后得到两个 JS 文件,一个 main.bundle.js 是组件代码,另一个很长 vendors-node_modules_dayjs_dayjs_min_js-node_modules_react-dom_index_js.bundle.js 是库代码集合。
五,懒加载组件
const Child = React.lazy(()=>import('./child'));
import React from 'react';
import _ from 'lodash';
function Child() {
return <div>
Child {_.camelCase('Foo Bar')}
</div>
}
打包后发现又多了两个文件 src_child_js.bundle.js 和 vendors-node_modules_lodash_lodash_js.bundle.js 尝试在App组件中import lodash,会发现 vendors 开头的文件变成了一个 vendors-node_modules_dayjs_dayjs_min_js-node_modules_lodash_lodash_js-node_modules_react-dom_-423d76.bundle.js。
六,集成开发服务器
不想更新完还要丢到服务器才能看,所以需要一个可以编译后刷新页面就能看到最新效果的工具。 增加如下配置
devServer: {
contentBase: './dist',
}
sourcemap 自然也不能忘,从前端到后台调试 sourcemap 是必备
devtool: 'inline-source-map'
启动集成的服务器
webpack serve —config=webpack.base.js
然后就可以在浏览器看到啦,而且改了代码还会自动刷新页面哇
七,增加样式文件支持
直接使用 styl 吧,现在不会个 CSS 预处理器都不跟你打招呼 rules 规则里面增加配置
{
test: /\.styl$/,
include: /src/,
use: [
"style-loader",
"css-loader",
"stylus-loader",
]
}
然后,给 App 组件的按钮加一个样式
.btn {
padding: 4px 10px;
}
看下页面,好像没问题哎~ 别急,给 child 组件的按钮也加一个不同的样式 啊 发现了没! 类名冲突了,大家都是按钮,凭什么你可以叫 .btn 我不可以叫呢?(虽然严格遵守BEM就不会出现这种问题 啊哈哈哈哈)
{
test: /\.styl$/,
include: /src/,
use: [
"style-loader",
{
loader: "css-loader",
options: {
modules: true,
},
},
"stylus-loader",
]
},
组件使用也不是直接 import 进来就完了,变成了 import styles
八,使用三方 UI 库
对于 to B 来说,一套完整的 UI 是很庞大的,这里使用 antd。 上一步的 rule 要再加一点,之前只针对了 src 目录下的 css 文件,antd 的 css 也要支持
{
test: /\.css$/,
include: /node_modules/,
use: [
"style-loader",
"css-loader",
]
},
然后,再全局 css 中 import,或者入口组件中 import 都可以啦 啊哈,感觉还不错的样子! 但是...! 看看控制台! 没有 .css 文件加载,样式都放在 JS 里了,这不是徒增工作嘛?
该 MiniCssExtractPlugin 上场了,之前规则里的 "style-loader" 全部替换成 MiniCssExtractPlugin.loader,这样每个组件导入的 CSS 和库的 CSS 就全都是分开的啦~
九,热更新 HMR
每次改代码都要刷新页面,好不方便啊,所以上热更新
devServer: {
hot: true,
},
plugins: [
new webpack.HotModuleReplacementPlugin(),
]
入口也要添加
if(module.hot) {
module.hot.accept('./app.js', function(){
const App = require("./App").default;
ReactDOM.render(<App />, document.getElementById('root'));
});
}
哎这样改些代码呀,样式文件呀都可以实时局部更新啦 但是,react 的状态没了,react 要用专用库
import { hot } from 'react-hot-loader/root';
export default hot(App);
啊哈 这样状态就也能保持啦,还带一个小小的loading状态~
另外呀,Webpack 5 更新了缓存系统,所以之前的 dll,HardSource 等手段基本可有可无啦,方便了许多~
代码仓库:React Startkit