Webpack5配置

Tags
Published
Author
将支持以下功能:
  • 分离开发环境、生产环境配置
  • 模块化开发
  • 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
会将 DefinePluginprocess.env.NODE_ENV 的值设置为 development。为模块和 chunk 启用有效的名称。
  • production
会将 DefinePlugin 中 process.env.NODE_ENV 的值设置为 production。为模块和 chunk 启用确定性的混淆名称,FlagDependencyUsagePluginFlagIncludedChunksPluginModuleConcatenationPluginNoEmitOnErrorsPlugin 和 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打包编译
编译后,会生成这样的目录结构:
notion image
打包编译结果

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,自动引入所有bundle new HtmlWebpackPlugin({ title: 'release_v0', }), ],}
重新 webpack 编译npx webpack --config config/webpack.prod.js,生成的目录结构如下
notion image
打包入html
新生成了 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-loaderurl-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@importurl() 进行处理,就像 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 features modules: 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/core Babel 编译的核心包
  • @babel/preset-env Babel 编译的预设,可以理解为 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.jsontsconfig相关提示
{ "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包,并减少输出的大小 }}