Webpack入门,这一篇就够了 | 您所在的位置:网站首页 › 修改webpack配置 › Webpack入门,这一篇就够了 |
前言 众所周知,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 的内容: webpack5app.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: 1 和 is 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.jsnpx 是先从本地找到相应的模块,找不到再下载,所以使用 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.jsindex.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: aquaapp.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.jsindex.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.jsapp.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 -Dpostcss 是通过 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、压缩 CSSwebpack 的插件能够增强 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 默认在生产模式在才生效),打包后效果如下: DevServerdevserver 可以在本地启动一个服务,使我们可以使用 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 实验室设备网 版权所有 |