现在前端开发越来越偏向模块化,我们的项目也逐渐转向脚手架搭建。这其中,webpack的力量是巨大的,之前因为不了解webpack的某些配置所以在项目中也耽搁了一些时间,因此我觉得很有必要深入了解下webpack。之后需要自己尝试手动搭建项目工程,才能真正理解脚手架的原理。
webpack
官方的话来说,Webpack 是一个模块打包器。它将根据模块的依赖关系进行静态分析,然后将这些模块按照指定的规则生成对应的静态资源。
接下来让我们安装并初步配置下webpack4吧~
全局安装
全局安装,安装成功之后可以在全局使用webpack:
1 | npm install -g webpack |
全局安装失败可能是网络的原因,可以使用淘宝镜像安装:
1 | cnpm install webpack -g |
栗子初体验
初始化
新建一个文件夹weproject并初始化项目:
1 | cd weproject |
npm init会自动创建一个package.json文件,这个文件存放着当前项目的相关信息。
安装webpack
在项目中安装webpack:
1 | npm install --save-dev webpack webpack-cli |
构建目录
新建文件夹src
1 | mkdir src |
在src文件夹中新建一个index.js。该文件是webpack的入口文件。webpack打包后会自动生成一个dist文件夹,默认生成构建文件main.js。
1 | //index.js |
在src文件夹中新建一个新建静态页面index.html,方便之后查看效果:
1 |
|
webpack4是可以不用手动配置(webpack会提供一套默认配置),但如果需要自定义配置,我们可以新建一个webpack的配置文件webpack.config.js,通过配置文件可以告诉webpack需要做些什么。
如下,在该文件中配置了入口文件和输出文件的路径:
1 | let path = require('path') |
PS: 可以通过npx直接执行node_modules中的依赖。
执行webpack
在文件夹中执行命令webpack可以看到打包后的js文件在自动生成的dist文件夹中:
1 | webpack //或者 webpack --mode development |
在浏览器打开index.html可以查看效果,说明webpack把src/index.js文件打包成dist/main.js了。
修改执行命令
只需在package.json的scripts中加入:
1 | "scripts": { |
就可以用npm run dev代替webpack,用npm run build代替webpack --mode production了。
新建模块
新建一个module.js:
1 | //module.js |
在index.js中引用module.js:
1 | // ... |
重新执行npm run dev打开页面可以看到页面变化。webpack会分析入口文件,并解析包含依赖关系的文件,把他们都打包到main.js中。
让配置文件支持智能提示
通过 Configuration 让 VSCode 提供webpack配置的智能提示,修改webpack.config.js为:
1 | // 运行webpack时注释下面这句 |
到这里我们就初步了解了webpack的安装和使用啦,不过如果要实现更多自定义功能的话,我们还需要了解webpack的几个核心概念。
webpack核心概念
webpack的核心有以下几点:
- Entry:入口
- Output:出口
- Loader:加载器
- Plugins:插件
- Mode:模式
Entry
入口文件,默认是src/index.js,entry可以是字符串(单入口),可以是数组或对象(多入口),如下:
1 | module.exports = { |
或
1 | module.exports = { |
webpack会解析多个入口文件的依赖后进行打包。
Output
输出文件,是一个对象,webpack默认创建的输出内容就是 ./dist/main.js。也可以自定义路径:
1 | // webpack.config.js运行在nodeJs环境中,可以使用nodeJS的内置模块 |
path
表示生成文件的根目录,需要传入一个绝对路径。path参数和后面的filename参数共同组成入口文件的完整路径。
publicPath
表示一个URL路径(指向生成文件的根目录),用于生成css/js/图片/字体文件等资源的路径。 publicPath参数跟path参数的区别是:path参数其实是针对本地文件系统的,而publicPath则针对的是浏览器,因此,publicPath既可以是一个相对路径,也可以是一个绝对路径。
filename
表示如何命名生成出来的入口文件
chunkFilename
chunkFilename参数与filename参数类似,都是用来定义生成文件的命名方式的,只不过,chunkFilename参数指定的是除入口文件外的chunk(这些chunk通常是由于webpack对代码的优化所形成的,比如因应实际运行的情况来异步加载)的命名。
Loader
Webpack 本身只能处理 JavaScript 模块,如果要处理其他类型的文件(如css,图片,字体等),就需要使用 loader 进行转换。可以理解为Loader 将各个类型的文件,转换为JS代码能够为webpack所打包。
Loader 可以在require()引用模块的时候添加,也可以在 webpack 全局配置中进行绑定,还可以通过命令行的方式使用。
打包css(css-loader)
新建一个文件style.css:
1 | body { background: #fc9; } |
加载css需要安装以下loader:
1 | npm install css-loader style-loader --save-dev |
过程:css-loader将css模块转成js交给webpack打包,style-loader将css打包结果通过style标签添加到页面上。
修改webpack.config.js:
1 | // ... |
在index.js中引用css文件(webpack建议在js文件中引入css等资源文件,更方便建立依赖关系):
1 | // ... |
重新执行打包,打开页面就可以看到背景颜色了。
处理图片
我们添加图片在项目中后(我的图片统一放在项目的img文件夹下),可以在style.css中继续补充:
1 | .box { |
在index.html中添加一个div:
1 | <div class="box"></div> |
加载图片需要安装以下loader:
1 | npm install url-loader --save-dev |
修改webpack.config.js,在module.rules中加入配置:
1 | //... |
重新执行打包就可以看到效果了。
- file-loader:能够根据配置项复制使用到的资源到构建之后的文件夹,并且能够更改对应的链接。
- url-loader :包含 file-loader 的全部功能,并且能够根据配置将符合配置的文件转换成 Base64 方式引入,将小体积的图片 Base64 引入项目可以减少 http 请求。
压缩图片
安装image-webpack-loader:
1 | npm install image-webpack-loader --save-dev |
修改配置项:
1 | // ... |
处理字体等(file-loader)
处理字体和图片差不多,首先我把下载的字体文件放在新建的icon文件夹,如下:
1 | npm install file-loader --save-dev |
修改webpack.config.js,在module.rules中加入配置:
1 | //... |
在入口文件引入iconfont.css, 并index.html中使用iconfont:
1 | <i class="iconfont icon-jia"></i> |
重新执行打包就可以看到效果了。
编译JS文件(babel-loader)
安装babel相关依赖:
1 | npm install babel-loader @babel/core @babel/preset-env --save-dev |
配置loader匹配JS文件:
1 | // ... |
Plugins
插件目的在于解决 loader无法实现的其他事,增强webpack在项目自动化构建方面的能力。插件接口功能极其强大,可以用来处理各种各样的任务。
想要使用一个插件,你只需要require()它,然后把它添加到 plugins 数组中。
自动构建html(html-webpack-plugin)
webpack支持自动创建html文件,首先得安装插件html-webpack-plugin:
1 | npm install html-webpack-plugin --save-dev |
然后在配置文件webpack.config.js中引用并调用该插件:
1 | // ... |
执行命令webpack会自动创建相应的html和js文件,并自动引用相应的静态资源文件。
如果需要自定义html路径或者增加其他配置,可以修改HtmlWebpackPlugin的参数:
1 | new HtmlWebpackPlugin({ |
自动生成html的优势:
- html输出在dist中,方便打包发布
- html中的script是自动引入的,确保资源文件路径正常
如果需要对html进行大量自定义,最好在源代码中添加生成html模板。如在src修改index.html作为模板:
1 |
|
修改插件配置:
1 | new HtmlWebpackPlugin({ |
如果在plugin中添加多个HtmlWebpackPlugin实例,可以打包出多个html。
1 | // ... |
压缩JS(terser-webpack-plugin)
压缩打包的js文件,可以减少文件体积。安装插件:
1 | npm i terser-webpack-plugin --D |
引入插件配置:
1 | const TerserPlugin = require('terser-webpack-plugin') |
清理dist文件夹(clean-webpack-plugin)
每次打包之后都会生成dist文件夹,而生成的文件夹不会清理掉之前遗留的文件,会造成不必要的资源浪费。因此我们打包之前最好删除之前的dist文件夹,或者配置自动清除dist文件夹的插件clean-webpack-plugin。
1 | npm i -D clean-webpack-plugin |
然后在配置文件webpack.config.js中引用并调用该插件:
1 | // ... |
这样我们下次打包的时候就会自动清理上次打包的文件啦~
复制文件(copy-webpack-plugin)
建议处理无需打包的静态文件(如图标等),一般把静态文件放在public或者static文件夹中,然后把该文件夹下所有文件直接复制到dist中,安装:
1 | npm i -D copy-webpack-plugin |
引用插件:
1 | // ... |
分析文件大小(webpack-bundle-analyzer)
安装一个可视化的打包分析工具:
1 | npm i webpack-bundle-analyzer --D |
在配置文件中修改:
1 | const BundlePlugin = require('webpack-bundle-analyzer') |
启动就可以看到文件大小分布图。
Mode
webpack的工作模式:
- production(默认):启动内置优化插件,自动优化打包结果,打包速度偏慢
- development: 自动优化打包速度,添加一些调试过程中的辅助插件
- none: 不会做优化操作,一般用于分析模块打包结果
其他优化
自动编译刷新(webpack-dev-server)
每次修改代码后,都需要执行打包命令重新打包才能看到新的页面效果,webpack提供一个代理服务器可以监听文件编号并自动重新编译:
1 | npm i webpack-dev-server --D |
在package.json中指定启动服务并自动打开浏览器的命令:
1 | //... |
修改配置指定server从哪里修改代码:
1 | module.exports = { |
如果需要启动热更新(HMR),即不刷新页面只更新部分模块,可以在配置文件的devServer中增加:
1 | module.exports = { |


