Webpack入门,这一篇就够了 您所在的位置:网站首页 修改webpack配置 Webpack入门,这一篇就够了

Webpack入门,这一篇就够了

2023-03-24 18:35| 来源: 网络整理| 查看: 265

前言

众所周知,Webpack 是一个打包工具。然而,很多人在学习后很快就会忘记,需要重新学习,而这样反复学习的过程非常繁琐。又因为看视频学习的速度太慢,所以本文提供了一个小 demo,从最基础的开始,逐步完善,最后配合 Vue CLI 一起配置(先不涉及原理),希望能够提供一个完整的知识回顾,让读者一篇文章就能够理清知识。

基本使用

Webpack是什么,能干什么,就不介绍了。

另外,本文基于 Webpack5!

初始化项目

首先用 npm init 创建 package.json 文件,然后再创建其他文件或文件夹,具体如下:

目录结构为:

webpack_demo/ ┣ src/ ┃ ┣ components/ ┃ ┃ ┣ common.js ┃ ┃ ┗ util.js ┃ ┗ app.js ┣ index.html ┗ package.json

其文件内容分别为:

package.json 的内容为默认的 init;

index.html 的内容:

webpack5

app.js 的内容:

import common from "./components/common"; import util from "./components/util"; common() util()

common.js 的内容:

export default function () { console.log('is common: ' + 1) }

util.js 的内容:

export default function () { console.log('is util: ' + 2) }

基于上面初始化出来的项目,可以看到,index.html 中引入了 app.js,然后 app.js 中又引入了 common.js 和 util.js 文件,最后运行 index.html,应该会输出 is common: 1is util: 2,但是在运行后,并没有如期的输出,而是报错了,如下:

控制台报错信息为:

Uncaught SyntaxError: Cannot use import statement outside a module

原因是浏览器不支持 import,那么就该 Webpack 登场了。

安装 Webpack

用下面命令安装 Webpack:

npm i webpack webpack-cli -D

分别安装了 webpack 和 webpack-cli,webpack 是本体,而 webpack-cli 则是 webpack 的执行依赖,能够命令式的执行 webpack。

安装好后,就可以使用 webpack 打包 src 下的 app.js 文件了,使之能够被浏览器使用。

命令式使用 Webpack:

打包方式就是直接使用 webpack,然后传入需要打包的文件就可以了。

用命令则在当前项目下直接执行 webpack ./src/app.js 就能够打包 app.js 文件了。

可以发现,webpack 是代表使用 webpack,而 ./src/app.js 是需要打包的文件。

webpack ./src/app.js

运行上面命令后,出现错误:

这是因为 webpack 是安装在项目中,而不是在全局,cmd 找不到 webpack 在哪,那么想要使用就得执行:

./node_modules/.bin/webpack ./src/app.js

这样就能成功打包了:

./node_modules/.bin/webpack 是主动找到 webpack 的所在位置进行执行。更方便的是可以使用 npx,如下:

npx webpack ./src/app.js

npx 是先从本地找到相应的模块,找不到再下载,所以使用 npx 就可以避免执行命令时编写过长的文件路径。

从上面还可以注意到,webpack 打包的时候有一个 Warning,大概意思是没有设置 mode,mode 可以指定打包的环境,这里在后面先加上 --mode=development(开发环境),正式环境和开发环境区分后面介绍:

npx webpack ./src/app.js --mode=development

这样就能完美打包了。

打包后的位置先不管。

命令式使用还有其他很多可以传递的参数,具体可看官方文档:

命令行接口(CLI) | webpack 中文文档

配置式使用 Webpack:

上面命令式的使用 webpack 需要手动的输入参数来告知 webpack 的打包环境,需要打包的文件等,这样每次打包都要输入很长的命令,非常麻烦。

所以 webpack 就提供了可以将参数配置化(大多数工具都是,方便使用),所以就需要在原有的基础上新增一个 webpack 的配置文件,此时项目目录的结构如下:

webpack_demo/ ┣ dist/ // 打包后生成的 ┃ ┗ main.js ┣ src/ ┃ ┣ components/ ┃ ┃ ┣ common.js ┃ ┃ ┗ util.js ┃ ┗ app.js ┣ index.html ┣ package.json ┗ webpack.config.js

在项目根目录新增一个 webpack.config.js (配置文件可以为 json,这里为 js,比较灵活) 文件,里面内容为:

module.exports = { entry: './src/app.js', // 需要打包的文件 mode: 'development' // 打包环境 }

然后再使用 npx webpack --config ./wenpack.config.js 执行即可:

--config 可以指定配置文件的位置,webpack 会找到相应的配置文件进行解析,从而打包。

所以就可以在 package.json 的 scripts 字段中配置脚本,就可快捷使用:

"scripts": { "dev": "webpack --config ./webpack.config.js" }

执行 npm run dev 即可。

结果

上面两种方式打包后,都会在项目根目录生成一个 dist 文件夹,文件夹里会有一个 main.js 文件(这是默认行为,可以指定打包后的位置和文件名称),所以还需要在 index.html 中修改引入的路径,如下:

再次运行 index.html,会发现可以正常输出了:

Webpack 的配置

webpack 不涉及原理的话那就是学它的配置,所以还是很简单的,下面将通过处理 CSS、图片等资源进行完善 demo。

基本配置

entry:表示 webpack 的入口,指定打包的文件,可以一个或多个。

output:表示输出文件的路径和文件名。

mode:表示打包环境,可设置 production 或 development 值。

看示例:

const path = require('path') module.exports = { entry: './src/app.js', output: { path: path.resolve(__dirname, 'dist'), filename: 'main.js', clean: true }, mode: 'development' }

上面配置会解析 src 下的 app.js 文件的相关依赖并打包,然后输出到当前项目的 dist 文件夹下,输出文件名为 main.js。

output 中的 clean 会在打包生成文件之前会按照这个字段的值进行清理行为,如果为 true,则清空 output 设定的目录下的文件。

模式为开发模式,开发模式可以编译 ES Module语法,而生成模式(production)则不仅可以编译 ES Module语法,还可以压缩代码。看对比:

production 模式把代码压缩成了一行,并且优化了代码。

Loader此部分内容包含:处理CSS、处理Less/Sass、处理图片、处理字体图标、处理CSS兼容性、处理JS兼容性

webpack 的 Loader 主要用于对模块的转换,也就是对文件的转化,如将 Less、Sass 处理成 CSS,将图片处理成 data URL 等。

在使用之前先来看下 Loader 在配置中的格式:

module.exports = { .... module: { rules: [] } }

先有一个 module 对象,其有一个 rules 字段,这个字段里边就是需要使用的 loader 了,如 css-loader:

module: { rules: [ { test: /\.css$/, use: ['style-loader', 'css-loader'] } ] } // 其他写法 module: { rules: [ { test: /\.css$/, loader: 'style-loader', } ] }

test 表示处理什么文件,用正则匹配,上面是只匹配后缀为 css 的文件,这样就只处理了 css 文件,而不会处理到其他文件;

当使用的是 loader 字段时,则只可以传入一个 loader,而使用 use 字段,可以传入多个 loader;

如果使用了多个 loader,则 webpack 在使用 loader 的时候是从右到左(从下到上)执行的,如有 ['style-loader', 'css-loader'],执行顺序是先执行 css-loader,然后再执行 style-loader。

相关文档: loader | webpack 中文文档

处理 CSS:

先在 src 下创建 css 文件夹,然后新建一个 css 文件,里边写一些样式代码,在 index.html 中新增 div,使样式生效,然后在 app.js 中引入,此时项目结构为:

webpack_demo/ ┣ src/ ┃ ┣ components/ ┃ ┃ ┣ common.js ┃ ┃ ┗ util.js ┃ ┣ css/ ┃ ┃ ┗ index.css ┃ ┗ app.js ┣ index.html ┣ package.json ┗ webpack.config.js

index.css 的内容为:

.box1 { width: 100px; height: 100px; background-color: red; }

app.js 内的内容为:

import common from "./components/common"; import util from "./components/util"; import './css/index.css' // 新增的引入 css common() util()

index.html 的内容为:

.... ....

一切就绪,打包....,然后报错了:

可以看到,在处理 CSS 的时候报错了,需要使用 Loader,也就是 webpack 是处理不了 CSS 等资源的,需要借助 Loader 或者 Plugins,处理 CSS 需要用到 css-loader 和 style-loader,不管是 Loader 还是 Plugins 都是 JS 模块,所以需要安装:

npm i css-loader style-loader -D

安装后修改 webpack 的配置如下:

const path = require('path') module.exports = { entry: './src/app.js', output: { path: path.resolve(__dirname, 'dist'), filename: 'main.js', }, mode: 'production', module: { rules: [ // 新增的loader { test: /\.css$/, use: ['style-loader', 'css-loader'], }, ], }, }

修改后再次打包,即可成功打包并显示正确结果:

css-loader:css-loader 会处理 import / reuqire 引入的内容:

将 app.js 中的 import './css/index.css' 解析得到其样式代码

style-loader:style-loader 则将样式插入到 html 中:

将 css-loader 解析得到的样式代码插入到 html 中

所以,处理 CSS 资源,css-loader 和 style-loader 两者不可缺其一。

处理 Sass、Less:

同样的,在 css 文件夹中新建一个 index.sass 文件和 index.less 文件,在 app.js 中引入,并在 index.html 中新增 div:

index.less 的内容:

.box2 { width: 100px; height: 100px; background-color: rgb(255, 174, 0); }

index.sass 的内容:

.box3 width: 100px height: 100px background-color: aqua

app.js 中新增:

import './css/index.less' import './css/index.sass'

index.html 中新增:

处理 Less 的 loader 为 less-loader,处理 Sass 的 loader 为 sass-loader,但同时需要安装 less 和 sass,以便能够将 less 和 sass 编译成 css:

npm i less less-loader sass sass-loader -D

安装后在 webpack.config.js 中新增 loader:

module.exports = { ...... module: { rules: [ ....... // 处理 less { test: /\.less$/, use: ['style-loader', 'css-loader', 'less-loader'], }, // 处理 sass { test: /\.sass$/, use: ['style-loader', 'css-loader', 'sass-loader'], } ] } }

上面 less-loader 和 sass-loader 将 less/sass 文件处理成 css 文件,然后再由 css-loader 和 style-loader 处理 css。

再次打包后可成功看到结果:

处理图片:

在项目中的 src 下新建 images 文件夹,并放入两张图片,在 index.css 中新增 CSS 代码,并在 index.html 中新增 div:

此时项目结构为:

webpack_demo/ ┣ src/ ┃ ┣ components/ ┃ ┃ ┣ common.js ┃ ┃ ┗ util.js ┃ ┣ css/ ┃ ┃ ┣ index.css ┃ ┃ ┣ index.less ┃ ┃ ┗ index.sass ┃ ┣ images/ ┃ ┃ ┣ 1.jpg // 233kb ┃ ┃ ┗ 2.jpg // 188kb ┃ ┗ app.js ┣ index.html ┣ package.json ┗ webpack.config.js

index.css 中新增的内容为:

.img1 { width: 150px; height: 200px; background-image: url('../images/1.jpg'); background-size: cover; } .img2 { width: 150px; height: 200px; background-image: url('../images/2.jpg'); background-size: cover; }

index.html 中新增的内容为:

此时打包是打包不了的,需要配置相应的 loader,但是 webpack5 后不需要配置 loader,只要设置相应的资源类型即可:

所以在 webpack.config.js 中新增 loader 配置如下:

{ test: /\.(png|jpe?g|gif|svg|webp)$/, type: 'asset', parser: { dataUrlCondition: { maxSize: 200 * 1024 } } }

设定资源类型为 asset,并且通过 dataUrlCondition 设定小于 200kb 的图片转换成 base64,这里就会将 2.jpg 转换成 base64 嵌入到 html 中,重新打包后效果如下:

打包后输出的图片文件也只有一个:

上面可以看到,图片打包后的输出目录与 main.js 在同一目录,那如果要把图片打包放到 dist/static/images 目录下呢,那么就可以 使用 generator 字段:

{ test: /\.(png|jpe?g|gif|svg|webp)$/, type: 'asset', parser: { dataUrlCondition: { maxSize: 200 * 1024 } }, generator: { filename: 'static/images/[hash][ext][query]' } }

generator 中的 filename 指定存放的目录

[hash]: 表示hash值,后面可携带自定义位数,例如[hash:8]

[ext]:原文件扩展名

[query]:添加之前的query参数

这样就可以把图片打包到其他位置了,看效果:

处理字体图标:

老样子,在 src 下新建一个 fonts 文件夹,然后在阿里巴巴矢量图标库中下载图标(这里使用 Font class 的使用方式,Symbol 体现不了),将下载的字体文件放到 fonts 文件夹中,将下载的 iconfont.css 文件放到 css 文件夹中,然后在 app.js 中引入,并在 index.html 中新增标签:

目录结构为:

webpack_demo/ ┣ src/ ┃ ┣ components/ ┃ ┃ ┣ common.js ┃ ┃ ┗ util.js ┃ ┣ css/ ┃ ┃ ┣ iconfont.css ┃ ┃ ┣ index.css ┃ ┃ ┣ index.less ┃ ┃ ┗ index.sass ┃ ┣ fonts/ ┃ ┃ ┣ iconfont.ttf ┃ ┃ ┣ iconfont.woff ┃ ┃ ┗ iconfont.woff2 ┃ ┣ images/ ┃ ┃ ┣ 1.jpg ┃ ┃ ┗ 2.jpg ┃ ┗ app.js ┣ index.html ┣ package.json ┗ webpack.config.js

app.js 新增内容为:

import './css/iconfont.css'

index.html 新增内容为:

还需要修改 iconfont.css 文件中引入字体文件的路径:

最后,在 webpack.config.js 中新增配置:

module.exports = { ...... module: { rules: [ ...... { test: /\.(ttf|woff|woff2)$/, type: 'asset/resource', generator: { filename: 'static/font/[hash][ext][query]' } } ] } }

asset/resource 能够将资源原封不动的输出到指定位置:

处理 CSS 兼容性:

通过 loader,可以将一些较新的 CSS 语法能够在低版本浏览器中使用,而这个 loader 就是 postcss-loader,但这个 loader 还依赖 postcss 和 postcss-preset-env,所以需要安装三个模块:

npm i postcss-loader postcss postcss-preset-env -D

postcss 是通过 JS 来转换样式,而 postcss-preset-env 则能够加强 CSS 的兼容性,所以 postcss-loader 依赖这两者,修改 webpack 的配置如下:

除了修改以上配置以外,在 package.json 中新增:"browserslist": ["ie >= 7"]

{ "name": "webpack_demo", "version": "1.0.0", "description": "", "main": "index.js", "scripts": { "dev": "webpack --config ./webpack.config.js" }, "author": "", "license": "ISC", "devDependencies": { .... }, "browserslist": ["ie >= 7"] }

在 index.css 中新增 display: flex; :

.box1 { width: 100px; height: 100px; background-color: red; display: flex; }

打包后可看到做了兼容性处理:

处理 JS 兼容性:

通过 loader ,还可以将 JS 语法在较低的浏览器版本中使用,主要就是通过 babel,同样需要安装三个模块,一个 laoder,一个核心库,一个预设,分别就是 babel-loader、@babel/core、@babel/preset-env:

npm i babel-loader @babel/core @babel/preset-env -D

安装后,在 webpack.config.js 中新增 laoder 配置如下:

{ test: /\.js$/, exclude: /node_modules/, use: ['babel-loader'] }

exclude 排除 node_modules 下的文件;

这样配置还不行,@babel/preset-env 才是主要转换代码的东西,为了后面方便修改,在项目根目录新建一个 babel.config.js 配置文件:

module.exports = { presets: ['@babel/preset-env'] }

配置后,在 app.js 中写一些 ES6 语法,打包后就会转换成 ES5 的语法

在 app.js 中新增以下代码:

function count(...arg) { console.log(arg[0] + arg[1]) } count(1,2)

打包后查看代码会发现已经转换了:

Plugins此部分内容有:提取 CSS 为单独文件、自动引入 JS 和 CSS、压缩 CSS

webpack 的插件能够增强 webapck 的功能,本身 webpack 只是解析依赖从而打包,loader 使 webpack 能够转化文件,而 plugins 则使 webpack 能够拥有压缩,提取等更大强大的功能。

webpack 的插件主要在 plugins 字段上,是个数组,也就是可以使用多个插件,每个插件在使用的时候都必须传入一个 new 实例。

提取 CSS 为单独文件:

上面通过 loader 处理 css 时,css 是通过 JS 直接插入到 html 中,不是用引入链接的方式,这样在访问页面解析 JS 到解析完成会有一个突然出现的效果,影响体验。

通过 MiniCssExtractPlugin 插件可以将 CSS 提取到单独的文件中。

https://webpack.docschina.org/plugins/mini-css-extract-plugin#root

相关文档:MiniCssExtractPlugin | webpack 中文文档

安装这个插件:

npm install mini-css-extract-plugin -D

然后修改 webpack 的配置:

引入 mini-css-extract-plugin,然后在 plugins 中设置,最后将 style-loader 替换成 MiniCssExtractPlugin.loader。

打包后:

打包后确实将 css 提取到单独的文件里了,但是 html 中还需要手动引入:

自动引入 JS 和 CSS:

上面打包后,不管是 JS 还是 CSS 打包为单独文件时,在 index.html 中都需要手动引入相应的资源,如果修改了 webpack 打包 JS 和 CSS 文件的路径,那么 index.html 也需要修改。

基于以上问题,可以通过 HtmlWebpackPlugin 插件解决。

相关文档:HtmlWebpackPlugin | webpack 中文文档

安装这个插件:

npm i html-webpack-plugin -D

然后修改 webpack 配置:

先引入 html-webpack-plugin,然后将其添加到 plugins 中,同时将 index.html 中引入 css 和 js 的代码注释。

打包后,可看到在 dist 下有一个 index.html :

同时帮你自动引入了相关的资源,这时就可以访问这个新的 index.html 来查看效果了。

在配置 html-webpack-plugin 时,如果没有传入 template,生成的 index.html 的内容则是这样的:

我们自己写的一些 div 不见了,所以传入 template 的作用就是让 html-webpack-plugin 以一个 html 文件为模板去生成一个新的 html 文件。

压缩 CSS:

同样的,使用 CssMinimizerWebpackPlugin 这个插件能够将 CSS 压缩为一行,减少文件体积。

安装这个插件:

npm i css-minimizer-webpack-plugin -D

然后修改 webpack 配置:

还是那样,引入 css-minimizer-webpack-plugin,然后在 plugins 中添加,最后修改 mode(css-minimizer-webpack-plugin 默认在生产模式在才生效),打包后效果如下:

DevServer

devserver 可以在本地启动一个服务,使我们可以使用 http 协议去访问 index.html ,并且当修改代码时,能够监听当前项目的文件变动从而实现自动打包,而不用每次修改后都要手动打包:

在 webpack 配置中添加 devServe 字段,里边配置 host、port等。同时还需要安装 webpack-dev-server 模块:

npm i webpack-dev-server -D

同时,webpack 打包命令也需要添加一个 serve 参数才能调用 webpack-dev-server:

启动 server 前,可以先将 dist 目录下的文件清空,然后再运行 npm run dev,可以发现 dist 下并没有生成任何文件,这是因为,server 打包后是放在内存中的,所以 dist 下也不需要任何文件,server 一般是在开发环境下使用的,如果在生成环境,就需要打包到本地了。

总结

上面通过处理各种资源来介绍 webpack 的配置使用,但只介绍了其中一部分,更多的 loader,plugins 等使用方法还是得到官方文档查询。

只要理解 webpack 的 entry、output、loader、plugins、mode 就非常简单,其余的查询官方文档即可。

开发模式与生产模式

经过上面的配置,webpack 配置是有 development 和 production 区分的,在开发环境下,通过 devserver 启动,就不会 dist 文件夹,而生产模式下又恰恰需要,为了避免在两种模式打包而需要来回修改 webpack 的配置文件的内容,可以通过判断当前打包环境,从而决定是否需要 devServer 或者 设置 mode 值等:

上面就是通过判断 process.env.NODE_ENV 的值来决定是否使用 devServer。

上面配置好后,还需要在 package.json 的 scripts 中添加 build 命令,以便方便打包:

build 就不需要 serve 参数了,这样虽然可以打包,但是会发现有 warning,提示 mode 没有设置,这时打印 process.env.NODE_ENV 的值为 undefined,所以会报 warning。

可以使用 cross-env 模块来设置 node 的环境变量:

npm i cross-env -D

同时修改 scripts:

这样就能解决问题了。

未完待续........

码字不易,请多多点赞。

欢迎关注 @加里敦权威指南

前端知识分享,让你日日有收获


【本文地址】

公司简介

联系我们

今日新闻

    推荐新闻

      专题文章
        CopyRight 2018-2019 实验室设备网 版权所有