|
[webpack中文文档](概念 | webpack 中文文档 | webpack中文文档 | webpack中文网 (webpackjs.com)):
本质上,webpack 是一个用于现代 JavaScript 应用程序的 静态模块打包工具。当 webpack 处理应用程序时,它会在内部从一个或多个入口点构建一个 依赖图(dependency graph),然后将你项目中所需的每一个模块组合成一个或多个 bundles,它们均为静态资源,用于展示你的内容。
这篇笔记主要记录的是Webpack 5。
基本使用
安装
安装webpack的同时需要安装webpack-cli。- npm i webpack webpack-cli -D
复制代码 启动
启动分为开发模式和生产模式。
- npx webpack /path/to/main.js --mode=development
复制代码- npx webpack /path/to/main.js --mode=production
复制代码 其中:
- npx webpack:用于运行本地安装的webpack;
- /path/to/main.js:指定webpack从main.js开始打包,会同时打包其依赖文件;
- --mode=xxx:指定模式。
注:
如果终端输出webpack is not recognized as an internal or external command,即无法被识别为指令。
那么可以考虑将webpack进行全局安装:- npm i -g webpack webpack-cli
复制代码 输出
webpack会默认将文件打包输出到dist文件夹,并且只能处理js资源。
如果需要处理其它资源文件,或者需要更精细化地打包,则需要设置webpack的配置文件:webpack.config.js。
Webpack的配置
webpack的配置文件命名为webpack.config.js,置于项目文件的根路径下。
webpack是基于node运行的,所以webpack.config.js采用CommonJS模块化规范。
webpack的配置有五大核心概念:
- entry(入口):webpack从这个文件开始进行打包,并打包其依赖文件;
- output(输出):决定了webpack打包后的文件的文件名、地址等;
- loader(加载器):webpack只能处理js文件,其它文件比如css文件、图片资源、jsx文件,需要使用loader才能解析;
- plugins(插件):扩展webpack的功能,每一个插件如何配置取决于插件的提供者如何设计;
- mode(模式):主要有两种模式,开发模式(development)和生产模式(production)。
简单的配置文件样例:- // Node.js的核心模块,专门用来处理文件路径
- const path = require("path");
- module.exports = {
- // 入口
- // 相对路径和绝对路径都行
- entry: "./src/main.js",
- // 输出
- output: {
- // path: 文件输出目录,必须是绝对路径
- // path.resolve()方法返回一个绝对路径
- // __dirname 当前文件的文件夹绝对路径
- path: path.resolve(__dirname, "dist"),
- // filename: 输出文件名
- filename: "main.js",
- },
- // 加载器
- module: {
- rules: [],
- },
- // 插件
- plugins: [],
- // 模式
- mode: "development", // 开发模式
- };
复制代码 在上面基本使用那一栏里,由于没有配置文件,运行webpack的时候通常会带上后缀:npx webpack /path/to/main.js --mode=development,用于指定入口文件、模式等信息。
添加配置文件之后,webpack会自动读取webpack.config.js这个文件里的配置信息,因此可以直接运行:npx webpack。
开发模式介绍
通常会创建两个配置文件,一个对应开发模式,另一个对应生产模式。
开发模式的webpack主要需要完成以下任务:
- 编译代码,使浏览器能识别运行
webpack只能处理js文件,而其它文件,例如:css文件、字体图标、图片资源、html资源等,webpack需要通过配置loader才能处理这些资源;
- 代码质量检查
使用例如eslint之类的代码检查工具,提前发现代码缺陷,也可以检查代码书写是否规范,统一团队编码风格。
处理样式资源
需要使用css-loader和style-loader才能处理css文件。
- css-loader:负责将CSS文件编译成webpack可以识别的模块。
- style-loader:会动态地创建一个style标签,用于放置webpack 中的css模块。
先安装:- npm i css-loader style-loader -D
复制代码 配置webpack:- const path = require("path");
- module.exports = {
- entry: "./src/main.js",
- output: {
- path: path.resolve(__dirname, "dist"),
- filename: "main.js",
- },
- module: {
- rules: [
- {
- // 用来匹配 .css 结尾的文件
- test: /\.css$/,
- // use 数组里面 Loader 执行顺序是从右到左
- use: ["style-loader", "css-loader"],
- },
- ],
- },
- plugins: [],
- mode: "development",
- };
复制代码 这里需要注意的是:use字段指定需要应用的loader,顺序是从右到左的,即css文件先经由css-loader变成webpack可以识别的模块,然后再由style-loader将这些模块注入到html里。
这里提供案例的相关代码:
- /src/assets/css/style.css
- #app{
- text-align: center;
- font-weight: bold;
- }
复制代码- export function show(dom, msg){
- dom.innerText = msg;
- }
复制代码- import {show} from './js/show'
- import './assets/css/style.css'
- const app = document.getElementById('app');
- show(app, 'Hello Webpack');
复制代码- <!DOCTYPE html>
- <html lang="en">
- <head>
- <title>webpack-learning</title>
- </head>
- <body>
-
-
- </body>
- </html>
复制代码 同时,可以在package.json中设置常用的指令:- {
- ...
- "script":{
- "start": "webpack --config webpack.config.js"
- },
- ...
- }
复制代码 然后,只需要在终端运行:就会以webpack.config.js为配置,运行webpack,将main.js及其依赖文件,打包到/dist/main.js。
此时,打开/public/index.html,可以看到依赖的js文件show函数的功能正常,且引入的style.css样式也被打包并注入到style标签中:
常用的样式资源还有Less,Sass等,这里再介绍Less样式表的处理,其它样式资源的处理方式是类似的。
首先安装相应的loader:配置webpack:在webpack.config.js文件原有的基础上进行修改。- ...
- module.exports = {
- ...
- module: {
- rules: [
- ...
- {
- // 用来匹配 .less 结尾的文件
- test: /\.less$/,
- use: ['style-loader', 'css-loader', 'less-loader']
- }
- ]
- },
- ...
- }
复制代码 上述代码中的...表示原有的,但是这里为了突出重点而省略的代码片段。
配置less-loader只需要在rules数组中添加新的一项,注意use的顺序是从右到左,先把less代码转换成css代码,然后依此类推。
这里我只是在上述css的代码中做了一些修改:
- 新增/src/assets/less/style.less文件
- #app{
- text-align: center;
- font-weight: bold;
- }
复制代码
- /src/main.js中不引入css文件,而是引入less文件
- import {show} from './js/show'
- import './assets/less/style.less'
- const app = document.getElementById('app');
- show(app, 'Hello Webpack');
复制代码
- 执行npm run start
- 打开/pubcli/index.html,可以观察到less也能被正确地处理并注入到最终的style标签中。
这里再浅浅地提一嘴关于Sass/Scss的样式资源处理配置,他们的loader都是使用sass-loader,因此,在配置test的时候,正则表达式可以使用:/\.s[ac]ss$/去同时匹配这两种文件后缀。
处理图片资源
过去的Webpack4 ,处理图片资源需要使用file-loader和url-loader。
现在Webpack5已经将两个Loader功能内置到Webpack里了,只需要简单配置即可处理图片资源。
- ...
- module.exports = {
- ...
- module: {
- rules: [
- ...
- {
- test: /\.(png|jpe?g|gif|webp)$/,
- type: "asset",
- },
- ],
- },
- ...
- };
复制代码 相关代码:
- 在代码中引入图片(记得需要出现在入口文件的依赖中,否则不会被webpack处理)
- body{
- background-image: url('../images/normal.png');
- }
- #app{
- text-align: center;
- font-weight: bold;
- background-image: url('../images/small.png');
- }
复制代码图片可以随便照几张测试,这里我习惯性地将图片放在/src/assets/images目录下。
上面样式资源打包后没有相应的样式资源出现是因为:经过style-loader的处理,样式资源被打包进了/dist/main.js。
对图片资源进行优化:将小于某个大小的图片转换成Base64格式。- ...
- module.exports = {
- ...
- module: {
- rules: [
- ...
- {
- test: /\.(png|jpe?g|gif|webp)$/,
- type: "asset",
- parser: {
- dataUrlCondition: {
- maxSize: 10 * 1024 // 小于10kb的图片会被base64处理
- }
- }
- },
- ],
- },
- ...
- };
复制代码这里我用于测试的两张图片:normal.png和small.png,其中normal.png大于10kb,而small.png小于10kb。
再次打包并运行:
可以看到小于10kb的图片文件被转换成Base64格式。
- 优点:减少请求数量
- 缺点:main.js体积变得更大
修改输出资源的名称和路径
- module.exports = {
- ...
- output: {
- path: path.resolve(__dirname, "dist"),
- filename: "static/js/main.js", // 将 js 文件输出到 static/js 目录中
- },
- module: {
- rules: [
- ...
- {
- test: /\.(png|jpe?g|gif|webp)$/,
- type: "asset",
- parser: {
- dataUrlCondition: {
- maxSize: 10 * 1024, // 小于10kb的图片会被base64处理
- },
- },
- generator: {
- // 将图片文件输出到 static/imgs 目录中
- // 将图片文件命名 [hash:8][ext][query]
- // [hash:8]: hash值取8位
- // [ext]: 使用之前的文件扩展名
- // [query]: 添加之前的query参数
- filename: "static/imgs/[hash:8][ext][query]",
- },
- },
- ],
- },
- ...
- };
复制代码 上述配置在原来的基础上,修改了:
- main.js的输出目录;
- 图片文件的输出目录以及名称。
修改了main.js的输出路径之后,需要修改/public/index.html中的[/code]自动清空上次打包的资源
如果想要每次打包自动覆盖上一次打包生成的资源,使用clean: true- module.exports = {
- entry: "./src/main.js",
- output: {
- path: path.resolve(__dirname, "dist"),
- filename: "static/js/main.js",
- clean: true, // 自动将上次打包目录资源清空
- },
- module: {
- rules: [
- ...
- ],
- },
- ...
- };
复制代码 处理字体图标资源
字体图标可以到阿里巴巴矢量图标库下载。
下载到本地后解压并添加到项目中的文件夹,这里只需要以下文件:
- src/fonts/iconfont.ttf
- src/fonts/iconfont.woff
- src/fonts/iconfont.woff2
- src/css/iconfont.css
将文件分开放置需要修改iconfont.css中对于字体文件的引用路径:- @font-face {
- font-family: "iconfont"; /* Project id 4000108 */
- src: url('../fonts/iconfont.woff2?t=1695445577878') format('woff2'),
- url('../fonts/iconfont.woff?t=1695445577878') format('woff'),
- url('../fonts/iconfont.ttf?t=1695445577878') format('truetype');
- }
复制代码 然后在/public/index.html中使用字体图标:- [/code]配置webpack:
- [code]...
- module.exports = {
- ...
- module: {
- rules: [
- ...
- {
- test: /\.(ttf|woff2?)$/,
- type: "asset/resource",
- generator: {
- filename: "static/media/[hash:8][ext][query]",
- },
- },
- ],
- },
- ...
- };
复制代码 type: "asset/resource"和type: "asset"的区别:
- type: "asset/resource" 相当于file-loader, 将文件转化成 Webpack 能识别的资源,其他不做处理;
- type: "asset" 相当于url-loader, 将文件转化成 Webpack 能识别的资源,同时小于某个大小的资源会处理成 data URI 形式。
处理音频视频资源
音频和视频资源和字体图标做同样的处理,使用type: "asset/resource"。- ...
- module.exports = {
- ...
- module: {
- rules: [
- ...
- {
- test: /\.(ttf|woff2?|map4|map3|avi)$/,
- type: "asset/resource",
- generator: {
- filename: "static/media/[hash:8][ext][query]",
- },
- },
- ],
- },
- ...
- };
复制代码 处理JS资源
webpack只能编译JS中的ES模块化语法,其它更高级的功能需要配置才能使用。
常用的工具有Babel和Eslint:
- Babel用于将高版本的JS语法转换成ES5语法,是针对兼容性的;
- Eslint用于检查代码格式。
Eslint
Eslint可以用来检测JS和jsx语法。
使用Eslint需要写配置文件,标注各种rules,用于声明哪些代码规则需要检查。
在安装Eslint之前,先了解一下配置的写法:
- 新建配置文件.eslintrc.*:位于项目根目录
- .eslintrc
- .eslintrc.js
- .eslintrc.json
- 上面三种文件命名的区别在于文件类型不同,配置的格式不一样。
- 直接在package.json中的eslintConfig进行配置。
基本配置- module.exports = {
- // 解析选项
- parserOptions: {},
- // 具体检查规则
- rules: {},
- // 继承其他规则
- extends: [],
- };
复制代码
- parserOptions:解析选项
- parserOptions: {
- ecmaVersion: 6, // ES 语法版本
- sourceType: "module", // ES 模块化
- ecmaFeatures: { // ES 其他特性
- jsx: true // 如果是 React 项目,就需要开启 jsx 语法
- }
- }
复制代码 - rules具体规则
- off或0:关闭
- warn或1:警告
- error或2:报错
- rules: {
- semi: "error", // 禁止使用分号
- 'array-callback-return': 'warn', // 强制数组方法的回调函数中有 return 语句,否则警告
- 'default-case': [
- 'warn', // 要求 switch 语句中有 default 分支,否则警告
- { commentPattern: '^no default$' } // 允许在最后注释 no default, 就不会有警告了
- ],
- eqeqeq: [
- 'warn', // 强制使用 === 和 !==,否则警告
- 'smart' // https://eslint.bootcss.com/docs/rules/eqeqeq#smart 除了少数情况下不会有警告
- ],
- }
复制代码 - extends继承
直接引入已有的规则,常见的规则:
- Eslint官方的规则:eslint:recommended
- Vue-cli官方的规则:plugin:vue/essential
- React-cli官方的规则:react-app
如果本地的rules和继承的规则出现相同的选项,则本地的规则覆盖继承的规则。
安装Eslint- npm i -D eslint-webpack-plugin eslint
复制代码 定义配置文件:.eslintrc.js- module.exports = {
- // 继承 Eslint 规则
- extends: ["eslint:recommended"],
- env: {
- node: true, // 启用node中全局变量
- browser: true, // 启用浏览器中全局变量
- },
- parserOptions: {
- ecmaVersion: 6,
- sourceType: "module",
- },
- rules: {
- "no-var": 2, // 不能使用 var 定义变量
- },
- };
复制代码 配置webpack- ...
- const ESLintWebpackPlugin = require("eslint-webpack-plugin");
- module.exports = {
- ...
- plugins: [
- new ESLintWebpackPlugin({
- // 指定检查文件的根目录
- context: path.resolve(__dirname, "src"),
- }),
- ],
- ...
- };
复制代码 Babel
Babel的配置文件可以是下面的文件名之一:
- babel.config.js
- babel.config.json
- .babelrc
- .babelrc.js
- .babelrc.json
或者可以直接在package.json里的babel项进行配置。
以babel.config.js为例,基础配置为:- module.exports = {
- // 预设
- presets: [],
- };
复制代码 预设可以理解为是Babel插件,扩展Babel的功能。
- @babel/preset-env: 一个智能预设,允许您使用最新的 JavaScript;
- @babel/preset-react:一个用来编译 React jsx 语法的预设;
- @babel/preset-typescript:一个用来编译 TypeScript 语法的预设。
安装- npm i babel-loader @babel/core @babel/preset-env -D
复制代码 定义配置文件:babel.config.js- module.exports = {
- presets: ["@babel/preset-env"],
- };
复制代码 webpack配置- ...
- module.exports = {
- ...
- module: {
- rules: [
- ...
- {
- test: /\.js$/,
- exclude: /node_modules/, // 排除node_modules代码不编译
- loader: "babel-loader",
- },
- ],
- },
- ...
- };
复制代码 处理Html资源
之前没有处理html文件,所做的只是处理JS文件和其它资源,然后手动打开public/index.html。(/public/index.html需要手动引入打包后的dist/static/js/main.js文件)
安装- npm i html-webpack-plugin -D
复制代码 配置- ...
- const HtmlWebpackPlugin = require("html-webpack-plugin");
- module.exports = {
- ...
- plugins: [
- ...
- new HtmlWebpackPlugin({
- // 以 public/index.html 为模板创建文件
- // 新的html文件有两个特点:1. 内容和源文件一致 2. 自动引入打包生成的js等资源
- template: path.resolve(__dirname, "public/index.html"),
- }),
- ],
- ...
- };
复制代码 修改/public/index.html
我们的目标是使用html-webpack-plugin完成html文件的打包,现在/public/index.html不需要手动引入dist/static/js/main.js文件了,插件会自动完成这个任务,并把html文件也一并打包到/dist文件夹中。
打包并检查结果可以看到index.html也被打包了:
以下打包之后的/dist/index.html,可以看到被自动添加了 [/code]开发服务器与自动化
使用自动化代替原先的手动输入打包指令的操作。
安装依赖- npm i webpack-dev-server -D
复制代码 配置:(webpack.config.js文件)- ...
- module.exports = {
- ...
- // 开发服务器
- devServer: {
- host: "localhost", // 启动服务器域名
- port: "3000", // 启动服务器端口号
- open: true, // 是否自动打开浏览器
- },
- ...
- };
复制代码 修改package.json脚本- "scripts": {
- "start": "webpack --config webpack.config.js",
- "dev": "webpack serve --config webpack.config.js"
- },
复制代码 新加一个dev指令,用于启动本地服务。
运行指令启动服务之后,会自动打开浏览器(可能会被电脑的安全软件拦截,点击允许就行)。
默认启动热加载功能,此时修改源代码,会自动更新。
注:使用开发服务器的时候,代码不会被打包到/dist文件夹,而是编译打包在内存中。
生产模式介绍
开发完成代码之后,需要将代码打包给后端用于部署。
打包的配置需要考虑优化问题,主要从两个方面考虑:
注:
通常会使用两个配置文件来对应开发模式和生产模式,方便随时切换。
在项目根目录下创建文件夹:config。
然后新建两个配置文件:
- 开发模式配置文件:/config/webpack.dev.js
- 生产模式配置文件:/config/webpack.prod.js
在上文已经写好的webpack.config.js文件的基础上,稍作修改,拆分出两个模式的配置文件。
配置文件迁移的时候,由于目录变更,配置文件中的路径字符串需要做出相应的修改。同时,mode字段需要区分development或production。
开发模式需要注意:
- 没有输出,不需要指定输出路径,也不需要清空输出结果。
- 需要启动开发服务器。
生产模式需要注意:
更新package.json里的脚本- "scripts": {
- "start": "npm run dev",
- "dev": "webpack serve --config ./config/webpack.dev.js",
- "build": "webpack --config ./config/webpack.prod.js"
- },
复制代码
- 启动开发模式使用:npm run start或npm run dev
- 启动生产模式使用:npm run build
CSS处理
将css打包成单独文件
上文中的CSS处理是使用style-loader,这样做的结果是:样式会被打包到js文件中,最终再由js生成style标签。
这样做可能会导致白屏现象,因为目前流行的前端框架vue和react主要做的都是单页面应用,需要加载一个很大的js文件来渲染页面,如果样式也由js文件来负责的话,在js解析加载完成之前,页面内容一片空白。这样的页面用户体验不好。
因此,更好的解决方案是将CSS打包成单独的.css文件,然后使用引入。
安装相关的插件- npm i -D mini-css-extract-plugin
复制代码 配置webpack.build.js- ...
- // 引入插件
- const MiniCssExtractPlugin = require("mini-css-extract-plugin");
- module.exports = {
- ...
- module: {
- // css相关的rules,将style-loader替换成新插件的loader
- rules: [
- {
- // 用来匹配 .css 结尾的文件
- test: /\.css$/,
- use: [MiniCssExtractPlugin.loader, 'css-loader']
- },
- {
- // 用来匹配 .less 结尾的文件
- test: /\.less$/,
- use: [MiniCssExtractPlugin.loader, 'css-loader', 'less-loader']
- },
- ...
- ],
- },
- plugins: [
- ...
- // 提取css成单独文件
- new MiniCssExtractPlugin({
- // 定义输出文件名和目录
- filename: "static/css/main.css",
- }),
- ],
- mode: "production",
- };
复制代码 主要步骤:
- 引入插件;
- 修改rules中的loader;
- 新增plugins,并指定输出的文件名。
运行打包指令效果:
- 输出了/dist/static/css/main.css文件:
- 输出的/dist/index.html中出现了标签,并引入了打包后的css文件。
css兼容性处理
css兼容性处理可以使用postcss,拥有许多插件,可以按需配置,可以与解决JS兼容性问题的Babel进行类比。
安装
需要安装:
- postcss:postcss本身
- postcss-loader:为了webpack接入的loader
- postcss-preset-env:postcss官方提供的预设配置
- npm i -D postcss postcss-loader postcss-preset-env
复制代码 配置webpack.prod.js
只需要在css-loader之前新增一个postcss-loader就可以:- rules: [
- {
- // 用来匹配 .css 结尾的文件
- test: /\.css$/,
- use: [
- MiniCssExtractPlugin.loader,
- 'css-loader',
- // 在css-loader之前使用postcss-loader
- {
- loader: 'postcss-loader',
- options: {
- postcssOptions: {
- plugins: ['postcss-preset-env']
- }
- }
- }
- ]
- },
- {
- // 用来匹配 .less 结尾的文件
- test: /\.less$/,
- use: [
- MiniCssExtractPlugin.loader,
- 'css-loader',
- {
- loader: 'postcss-loader',
- options: {
- postcssOptions: {
- plugins: ['postcss-preset-env']
- }
- }
- },
- 'less-loader',
- ]
- },
- ]
复制代码 对于其它css扩展语法,例如less,可以先使用less-loader转成css,然后使用postcss-loader处理其兼容性,最后才是使用css-loader处理成webpack可以处理的模块,以及打包用的MiniCssExtractPlugin.loader。
兼容性控制
package.json文件中可以写入browserslist这个属性,指定兼容性的考虑程度。
这个属性是共用的,与兼容性问题相关的许多插件都会自动读取这个属性。
常用案例:- {
- "browserslist": ["last 2 version", "> 1%", "not dead"]
- }
复制代码 css压缩
减少打包后的体积。
安装- npm i -D css-minimizer-webpack-plugin
复制代码 配置- ...
- const CssMinimizerPlugin = require("css-minimizer-webpack-plugin");
- module.exports = {
- ...
- plugins: [
- ...
- // css压缩
- new CssMinimizerPlugin()
- ],
- mode: 'production'
- }
复制代码 html和js压缩
生产环境下,html和js是默认压缩的,即打包后的代码都是单行的。
总结
5个核心概念:
- entry(入口):webpack从这个文件开始进行打包,并打包其依赖文件;
- output(输出):决定了webpack打包后的文件的文件名、地址等;
- loader(加载器):webpack只能处理js文件,其它文件比如css文件、图片资源、jsx文件,需要使用loader才能解析;
- plugins(插件):扩展webpack的功能,每一个插件如何配置取决于插件的提供者如何设计;
- mode(模式):主要有两种模式,开发模式(development)和生产模式(production)。
2种模式
使用两个独立的配置文件。
- 开发模式:需要代码编译、语法检查、热加载。
- 生产模式:需要考虑性能与兼容性。
参考资料
来源:https://www.cnblogs.com/feixianxing/p/webpack-5-basic-usage.html
免责声明:由于采集信息均来自互联网,如果侵犯了您的权益,请联系我们【E-Mail:cb@itdo.tech】 我们会及时删除侵权内容,谢谢合作! |
本帖子中包含更多资源
您需要 登录 才可以下载或查看,没有账号?立即注册
x
|