# webpack-howto **Repository Path**: rhyanne/webpack-howto ## Basic Information - **Project Name**: webpack-howto - **Description**: 基于 Webpack 5 构建工具实战示例,探索 Webpack 的奥秘 - **Primary Language**: JavaScript - **License**: MulanPSL-2.0 - **Default Branch**: webpack-howto-react - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2022-06-24 - **Last Updated**: 2022-07-26 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # webpack-howto #### 介绍 基于 Webpack 5 构建工具实战示例,探索 Webpack 的奥秘 #### 主要目标 - 学些 Webpack5 的相关配置 - 基于 Webpack5 搭建 React 工程开发脚手架 - 基于 Webpack5 搭建 Vue3 工程开发脚手架 备注:每一个分支为独立的实战工程示例; #### 执行命令 ```shell # 安装 pnpm install # 开发环境 pnpm dev # 生产构建 pnpm build ``` ### 项目初始化 ```shell npm init -y ``` ### 安装 webpack ```shell # 当前版本 webpack@5.73.0 webpack-cli@4.10.0 pnpm add webpack webpack-cli -D # webpack-merge 用于区分开发和生产环境配置 pnpm add webpack-merge -D ``` ### 基础配置 新建 `config` 目录,用于存放配置文件:`paths.js`、`webpack.config.js`、`webpack.dev.js`、`webpack.prod.js`,分别为:路径变量定义、基础通用配置、开发环境配置、生产环境配置 ```javascript /// config/paths.js const path = require('path') const fs = require('fs') // Make sure any symlinks in the project folder are resolved. const appDirectory = fs.realpathSync(process.cwd()) // resolve path const resolveApp = relativePath => path.resolve(appDirectory, relativePath) module.exports = { appRoot: appDirectory, appSrc: resolveApp('src'), appBuild: resolveApp('build'), appPublic: resolveApp('public'), appIndexJs: resolveApp('src/main.js'), appHtml: resolveApp('public/index.html'), appDll: resolveApp('dll') } ``` 通用配置文件: ```javascript /// config/webpack.config.js const paths = require('./paths') // 到处工程函数,用于生产通用配置 module.exports = function (webpackEnv) { const isEnvProd = webpackEnv === 'production' const isEnvDev = webpackEnv === 'development' return { entry: paths.appIndexJs, output: { path: paths.appBuild, filename: isEnvProd ? "js/[name].[contenthash:8].js" : isEnvDev && "js/[name].bundle.js" }, // module: {}, // plugins: [], // resolve: {} } } ``` 开发环境配置文件: ```javascript /// config/webpack.dev.js const { merge } = require('webpack-merge') const configFactory = require('./webpack.config') // 设置全局环境变量 process.env.NODE_ENV = "development" // 通过工厂函数方法生成通用配置 const config = configFactory("development") // 合并通用配置和开发环境相关配置 module.exports = merge(config, { mode: 'development', }) ``` 生产环境配置文件: ```javascript /// config/webpack.prod.js const { merge } = require('webpack-merge') const configFactory = require('./webpack.config') // 设置全局环境变量 process.env.NODE_ENV = "production" // 通过工厂函数方法生成通用配置 const config = configFactory("production") // 合并通用配置和生产环境相关配置 module.exports = merge(config, { mode: 'production', }) ``` ### `html-webpack-plugin` 生成 `index.html` ```shell pnpm add html-webpack-plugin -D ``` ### `clean-webpack-plugin` 移除或清除构建目录下的文件 ```shell pnpm add clean-webpack-plugin -D ``` ### 集成 `ESLint` + `Prettier` ```shell pnpm add eslint prettier @babel/core @babel/eslint-parser eslint-config-prettier eslint-plugin-prettier -D pnpm add eslint-plugin-import eslint-plugin-react -D ``` 新建配置文件: ```shell ni .eslintrc.js ni .prettier.yaml # 或者 ni .prettierrc ni .prettierignore ni .editorconfig ``` ### 静态资源文件 —— `Asset Modules` 类型 静态资源主要包括:样式文件(CSS)、图片(Images)、字体(Fonts)、数据文件(Data)... 在 Webpack5 之前,比如 Webpack4 ,采用的是各种相关 `loaders` 来处理静态文件并打包的,比如:`css-loader`、`style-loader`、`url-loader`、`file-loader`、`raw-loader` 等; Webpack5 简化了之前版本对于文件方面的配置,提供了 `Asset Modules` (静态资源模块),替代了相关 `loaders`,使得处理静态资源更加方便; ```javascript // svg 转 data uri 编码算法插件 const svgToMiniDataURI = require("mini-svg-data-uri"); // module.rules rules: [ // 图片文件 { test: /\.(jpe?g|png|gif|webp)$/i, type: "asset", generator: { // 独立设置文件打包后的路径及文件名 filename: "images/[hash][ext][query]", }, parser: { dataUrlCondition: { maxSize: 4 * 1024, }, }, }, // SVG 文件 // SVG 文件转换为 URI 编码后,与 base64 相比,体积会更小 { test: /\.svg$/i, type: "asset", generator: { dataUrl: (content) => { content = content.toString(); // 通过插件提供的编码算法处理文件 return svgToMiniDataURI(content); }, filename: "images/[hash][ext][query]" }, parser: { dataUrlCondition: { // 2kb,低于 2kb 都会被压缩 maxSize: 2 * 1024, }, }, }, // 字体文件 { test: /\.(otf|eof|woff2?|ttf)$/i, type: "asset/resource", generator: { filename: "iconfonts/[hash][ext][query]", }, }, ] ``` 当 type 设置为 `asset` 是,webpack 会按照一下策略去打包文件: - 如果一个模块大小超过 8kb (默认值),使用 `asset/resource` ,被打包进输入文件夹中,类似 `file-loader` - 否则,就是用 `asset/inline`,内联到打包文件中,类似 `url-loader` > 区别:`asset/resource` 被单独放进输出文件中, `asset/inline` 被处理成 base64 编码字符串或者特定编码内联打包进输出的 JS 文件中 ### 样式文件处理 - `style-loader` 将样式文件以 `