基础配置
将支持以下功能:
- 分离开发环境、生产环境配置
- 模块化开发
- sourceMap 定位警告和错误
- 动态生成引入 bundle.js 的 HTML5 文件
- 实时编译
- 封装编译、打包命令
- 加载图片、字体、CSS、SCSS、PostCSS
- React+TypeScript
1.新建项目
mkdir REACT-CLIcd REACT-CLI// 初始化项目npm init -ymkdir srccd srccode index.js
2.安装 webpack
yarn add webpack webpack-cli -D
目录结构如下:
- node_modules- src- index.js- package.json
3.新建 webpack 配置文件
// 创建 config 目录mkdir config// 进入 config 目录cd ./config// Windows环境vscode创建通用环境配置文件code webpack.common.js// 创建开发环境配置文件code webpack.dev.js// 创建生产环境配置文件code webpack.prod.js
4.使用 webpack-marge 合并通用配置和特定环境配置
yarn add webpack-merge -D
通用环境配置::
// webpack.common.jsmodule.exports = {};
开发环境配置:
// webpack.dev.jsconst { merge } = require("webpack-merge");const common = require("./webpack.common");module.exports = merge(common, {}); // 暂不添加配置
生产环境配置:
// webpack.prod.jsconst { merge } = require("webpack-merge");const common = require("./webpack.common");module.exports = merge(common, {}); // 暂不添加配置
项目结构如下:
- config- webpack.common.js- webpack.dev.js- webpack.prod.js- node_modules- src- index.js- package.json
入口 entry
修改 webpack.commom.js:
module.exports = {// 入口entry: {index: './src/index.js',},}
输出(output)
output 属性告诉 webpack 在哪里输出它所创建的 bundle,以及如何命名这些文件。
生产环境的 output 需要通过 contenthash 值来区分版本和变动,可达到清缓存的效果,而本地环境为了构建效率,则不引入contenthash。
config目录下新增 paths.js,封装路径方法:
const fs = require('fs')const path = require('path')const appDirectory = fs.realpathSync(process.cwd());const resolveApp = relativePath => path.resolve(appDirectory, relativePath);module.exports = {resolveApp,appPublic: resolveApp('public'),appHtml: resolveApp('public/index.html'),appSrc: resolveApp('src'),appDist: resolveApp('dist'),appTsConfig: resolveApp('tsconfig.json')}
修改开发环境配置文件 webpack.dev.js:
const paths = require('./paths')module.exports = merge(common, {// 输出output: {// bundle 文件名称filename: '[name].bundle.js',// bundle 文件路径path: paths.appDist,// 编译前清除目录clean: true},})
修改生产环境配置文件 webpack.prod.js:
const paths = require('./paths')module.exports = merge(common, {// 输出output: {// bundle 文件名称 【只有这里和开发环境不一样】filename: '[name].[contenthash].bundle.js',// bundle 文件路径path: paths.appDist,// 编译前清除目录clean: true},})
[name]- chunk name(例如[name].js->app.js)。如果 chunk 没有名称,则会使用其 id 作为名称[contenthash]- 输出文件内容的 md4-hash(例如[contenthash].js->4ea6ff1de66c537eb9b2.js)
模式mode
通过 mode 配置选项,告知 webpack 使用相应模式的内置优化。
- development:
会将 DefinePlugin 中 process.env.NODE_ENV 的值设置为 development。为模块和 chunk 启用有效的名称。
- production:
会将 DefinePlugin 中 process.env.NODE_ENV 的值设置为 production。为模块和 chunk 启用确定性的混淆名称,FlagDependencyUsagePlugin,FlagIncludedChunksPlugin,ModuleConcatenationPlugin,NoEmitOnErrorsPlugin 和 TerserPlugin 。
修改开发环境配置文件 webpack.dev.js:
module.exports = merge(common, {// 开发模式mode: 'development',...})
修改生产环境配置文件 webpack.prod.js:
module.exports = merge(common, {// 生产模式mode: 'production',...})
Source Map
开发时,webpack 将我们写的代码经过编译后,很难追踪到 error 和 warning 在源代码中的原始位置。source map可以将编译后的代码映射回原始源代码。
修改开发环境配置文件 webpack.dev.js:
module.exports = merge(common, {// 开发工具,开启 source map,编译调试devtool: 'eval-cheap-module-source-map',})
source map 有许多 可用选项。本例选择的是 eval-cheap-module-source-map
完成上述配置后,可以通过 npx webpack --config config/webpack.prod.js打包编译
编译后,会生成这样的目录结构:

webpack-dev-server
在每次编译代码时,手动运行npx webpack --config config/webpack.prod.js会显得很麻烦,webpack-dev-server 可以帮助我们在代码发生变化后自动编译代码。
安装:
yarn add webpack-dev-server -D
修改开发环境配置文件 webpack.dev.js:
module.exports = merge(common, {devServer: {// 告诉服务器从哪里提供内容,只有在你想要提供静态文件时才需要。static: './dist',},})
完成上述配置后,可以通过 npx webpack serve --open --config config/webpack.dev.js 实时编译。
HtmlWebpackPlugin
引入 HtmlWebpackPlugin 插件,生成一个 HTML5 文件,其中会引用打包生成的 bundle 文件。
安装:
yarn add html-webpack-plugin -D
修改通用环境配置文件 webpack.commom.js:
module.exports = {...plugins: [// 生成html,自动引入所有bundlenew HtmlWebpackPlugin({title: 'release_v0',}),],}
重新 webpack 编译npx webpack --config config/webpack.prod.js,生成的目录结构如下

新生成了 index.html,修改了title,动态引入了 bundle.js 文件:
<!doctype html><html><head><meta charset="utf-8"><title>release_v0</title><meta name="viewport" content="width=device-width,initial-scale=1"><script defer="defer" src="index.7d02a7c9bcd86981b6f4.bundle.js"></script></head><body></body></html>
优化执行命令
上述配置文件完成后,优化 webpack 的实时编译、打包编译指令。
通过 cross-env 配置环境变量,区分开发环境和生产环境。
安装:
yarn add cross-env -D
修改 package.json:
"scripts": {"dev": "cross-env NODE_ENV=development webpack serve --open --config config/webpack.dev.js","build": "cross-env NODE_ENV=production webpack --config config/webpack.prod.js"}
现在可以运行 webpack 指令:
npm run dev:本地构建npm run build:生产打包
接下来继续完善配置,用 Webpack 搭建一个 SASS + TS + React 的项目,并且支持:
- 加载图片
- 加载字体
- 加载 CSS
- 使用 SASS
- 使用 PostCSS,并自动为 CSS 规则添加前缀,解析最新的 CSS 语法,引入 css-modules 解决全局命名冲突问题
- 使用 React
- 使用 TypeScript
加载图片、字体
在 webpack 5 中,有内置的 Asset Modules,不必再引入file-loader 和 url-loader处理文件了。
在实际开发过程中,推荐将大图片、字体文件压缩上传至 CDN,提高加载速度。
修改通用环境配置文件 webpack.commom.js:
const paths = require('./paths');module.exports = {...module: {rules: [{test: /\.(png|svg|jpg|jpeg|gif)$/i,include: paths.appSrc,type: 'asset/resource',},{test: /.(woff|woff2|eot|ttf|otf)$/i,include: [paths.appSrc,],type: 'asset/resource',},],},...}
加载CSS相关
- style-loader
style-loader 就是把 CSS 插入到 DOM 中,通过使用多个 <style></style> 自动把 styles 插入到 DOM 中.
- css-loader
css-loader 对 @import 和 url() 进行处理,就像 js 解析import/require()一样,让 CSS 也能模块化开发。
- sass-loader
sass-loader 会加载sass/scss文件并且将他们编译成CSS
- postcss-loader
1.可以自动为 CSS 规则添加前缀
2.将最新的 CSS 语法转换成大多数浏览器都能理解的语法
3.css-modules 解决全局命名冲突问题
安装相关库和依赖:
yarn add style-loader css-loader -Dyarn add sass-loader sass -Dyarn add postcss-loader postcss postcss-preset-env -D
修改通用环境配置文件 webpack.commom.js:
module.exports = {...module: {...rules: [{test: /\.css$/,include: paths.appSrc,use: [// 将 JS 字符串生成为 style 节点"style-loader",// 将 CSS 转化成 CommonJS 模块"css-loader",],},{test: /\.module\.(scss|sass)$/,include: paths.appSrc,use: [// 将 JS 字符串生成为 style 节点"style-loader",// 将 CSS 转化成 CommonJS 模块{loader: "css-loader",options: {// Enable CSS Modules featuresmodules: true,importLoaders: 2,// 0 => no loaders (default);// 1 => postcss-loader;// 2 => postcss-loader, sass-loader},},// 将 PostCSS 编译成 CSS{loader: "postcss-loader",options: {postcssOptions: {plugins: [[// postcss-preset-env 包含 autoprefixer"postcss-preset-env",],],},},},// 将 Sass 编译成 CSS"sass-loader",],},]}...}
JS相关
yarn add babel-loader @babel/core @babel/preset-env -D
babel-loader使用 Babel 加载 ES2015+ 代码并将其转换为 ES5@babel/coreBabel 编译的核心包@babel/preset-envBabel 编译的预设,可以理解为 Babel 插件的超集
使用 React + TypeScript
yarn add react react-dom @types/react @types/react-dom -Dyarn add typescript esbuild-loader -D//为提高性能,摒弃了传统的 ts-loader,选择最新的 esbuild-loader。
修改通用环境配置文件 webpack.commom.js:
module.exports = {resolve: {extensions: ['.tsx', '.ts', '.js'],},module: {rules: [{test: /\.(js|ts|jsx|tsx)$/,include: paths.appSrc,use: [{loader: 'esbuild-loader',options: {loader: 'tsx',target: 'es2015',},}]},]}}
为兼容 TypeScript 文件,新增 typescript 配置文件 tsconfig.json:tsconfig相关提示
{"compilerOptions": {"outDir": "./dist/","noImplicitAny": true,"module": "es6","target": "es5","strict": true,//通过启用TypeScript的strict编译器选项,编译器将在最严格的模式下运行,在运行之前捕获更多类型问题。"jsx": "react","allowJs": true,"moduleResolution": "node","allowSyntheticDefaultImports": true,"esModuleInterop": true,"forceConsistentCasingInFileNames": true,//强制统一不同操作系统的文件名"importHelpers": true,//通过启用TypeScript的importlpers编译器选项,编译器将使用tslib包,并减少输出的大小}}
