webpack5基础学习
本文主要记录webpack5的基础学习。最终代码放在文章末尾github上
什么是Webpack
一个打包编译静态资源的工具,可以把前端的静态资源进行打包压缩,有利于用户访问,减少带宽的占用
Webpack五大概念
官方Webpack五个概念:https://webpack.docschina.org/concepts/
入口(entry)
官网介绍:入口起点(entry point) 指示 webpack 应该使用哪个模块,来作为构建其内部 依赖图(dependency graph) 的开始。进入入口起点后,webpack 会找出有哪些模块和库是入口起点(直接和间接)依赖的。
默认值是
./src/index.js,但你可以通过在 webpack configuration 中配置entry属性,来指定一个(或多个)不同的入口起点
1
2
3 module.exports = {
entry: './path/to/my/entry/file.js',
};
入口起点(entry point)指示 webpack 应该使用哪个模块,来作为构建其内部依赖图的起点。进入入口起点后,webpack 会找出有哪些模块和库是入口起点(直接和间接)依赖的。
输出(output)
output 属性告诉 webpack 在哪里输出它所创建的 bundle,以及如何命名这些文件。主要输出文件的默认值是
./dist/main.js,其他生成文件默认放置在./dist文件夹中。你可以通过在配置中指定一个
output字段,来配置这些处理过程:
1
2
3
4
5
6
7
8
9 const path = require('path');
module.exports = {
entry: './path/to/my/entry/file.js',
output: {
path: path.resolve(__dirname, 'dist'),
filename: 'my-first-webpack.bundle.js',
},
};
output属性告诉 webpack 在哪里输出它所创建的 bundle,以及如何命名这些文件。
loader
webpack 只能理解 JavaScript 和 JSON 文件,这是 webpack 开箱可用的自带能力。loader 让 webpack 能够去处理其他类型的文件,并将它们转换为有效 模块,以供应用程序使用,以及被添加到依赖图中。
在更高层面,在 webpack 的配置中,loader 有两个属性:
test属性,识别出哪些文件会被转换。use属性,定义出在进行转换时,应该使用哪个 loader。webpack.config.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15 const path = require('path');
module.exports = {
output: {
filename: 'my-first-webpack.bundle.js',
},
module: {
rules: [
{
test: /\.txt$/,
use: 'raw-loader'
}
],
},
};
webpack 只能理解 JavaScript 和 JSON 文件。loader 让 webpack 能够去处理其他类型的文件,并将它们转换为有效模块,以供应用程序使用,以及被添加到依赖图中。
插件(plugin)
loader 用于转换某些类型的模块,而插件则可以用于执行范围更广的任务。包括:打包优化,资源管理,注入环境变量。
想要使用一个插件,你只需要
require()它,然后把它添加到plugins数组中。多数插件可以通过选项(option)自定义。你也可以在一个配置文件中因为不同目的而多次使用同一个插件,这时需要通过使用new操作符来创建一个插件实例。webpack.config.js
在这个示例中,
html-webpack-plugin为应用程序生成一个 HTML 文件,并自动将生成的所有 bundle 注入到此文件中。
1
2
3
4
5
6
7
8
9 const HtmlWebpackPlugin = require('html-webpack-plugin');
const webpack = require('webpack'); // 用于访问内置插件
module.exports = {
module: {
rules: [{ test: /\.txt$/, use: 'raw-loader' }],
},
plugins: [new HtmlWebpackPlugin({ template: './src/index.html' })],
};
loader 只能用于转换某些类型的模块,而插件则可以用于处理其他一些模块。包括:打包优化,资源管理,注入环境变量。
模式(mode)
通过选择
development,production或none之中的一个,来设置mode参数,你可以启用 webpack 内置在相应环境下的优化。其默认值为production。
1
2
3 module.exports = {
mode: 'production',
};
webpack 支持所有符合 ES5 标准 的浏览器(不支持 IE8 及以下版本)。webpack 的 import() 和 require.ensure() 需要 Promise。如果你想要支持旧版本浏览器,在使用这些表达式之前,还需要提前加载 polyfill。
1 | npm install --save babel-polyfill |
1 | import 'babel-polyfill'; |
如何使用
学习一门新的技术,应该最先最小化测试运行起来一个项目:
最小化安装使用
初始化项目:
1 | 初始化 |
因为webpack默认入口是src下的indexjs,所以我们根目录创建src,在src目录下创建index.js。
src/index.js
1 | console.log('hello webpack!') |
这时候我们直接运行:
1 | npx webpack |
这时候webpack就会以刚才的src/index.js文件为入口进行打包,打包后的文件会默认存放到dist目录下,我们也可以通过修改package.json文件的构建命令:
1 | "scripts": { |
这样我们就可以直接构建了。
完善配置
显然刚才只是一个极小的运行环境测试,webpack最主要还是配置文件,接下来我们在根目录创建webpack.config.js配置文件。(注意名称这里,默认是webpack.config.js,如果是需要改其他名,需要修改构建命令,具体参考https://webpack.docschina.org/configuration/)
webpack.config.js
1 | const path = require('path'); |
使用npm run bulid既可以构建出文件。
如果出于某些原因,需要根据特定情况使用不同的配置文件,则可以通过在命令行中使用
--config标志修改。package.json
1
2
3 "scripts": {
"build": "webpack --config prod.config.js"
}
经过上面的完善,我们配置了wecpack的配置文件,并且指明了开发环境,输入和输出,接下来继续完善
配置loader
JS是不认识CSS、图片或者其他的静态文件的,这时候我们就需要使用loader让JS来处理这些文件。
webpack4有三种,但是webpack只有两种方式,但是这里只列出官方推荐的配置方式:(具体可以参考:https://webpack.docschina.org/concepts/loaders)
我们处理CSS样式,这里需要下载:
1 | npm install style-loader css-loader -D |
webpack.config.js
1 | const path = require('path'); |
rules是一个数组,可以配置多个loader,loader对象里面有test和use属性,test是用来指出需要处理哪些文件的,use是指出用哪个loader处理。一个文件可以由多个loader处理。
接下来我们来解释一下module下rules的每个部分的作用:
test: /\.css$/: 这里定义了一个正则表达式,用于匹配所有以.css结尾的文件,表示这些文件需要被这个 loader 处理。use: 是一个 loader 数组,定义了处理.css文件的一系列 loader。style-loader: 这个 loader 将 CSS 插入到 DOM 中的<style>标签中,使得 CSS 样式生效。css-loader: 这个 loader 负责加载 CSS 文件,并且解析 CSS 文件之间的关系,比如@import和url()引用等。通过设置modules: true,启用了 CSS 模块化,使得每个 CSS 类名都局部作用域化,避免全局污染和命名冲突。
综合起来,这段配置的作用是:当 webpack 在打包过程中遇到以 .css 结尾的文件时,先用 css-loader 处理,然后用 style-loader 将处理后的样式通过 <style> 标签插入到页面中,同时实现了 CSS 的模块化管理。
需要注意的是,rules是有执行的顺序的,执行的顺序是书写顺序的倒序。
css-loader的 modules: true的设置:
不设置 modules: true 不会导致错误,但可能会影响你的 CSS 样式管理方式。两种设置的区别:
modules: true的情况:- 当
modules: true时,css-loader会将每个 CSS 类名编译成局部作用域的形式,通常是通过生成唯一的类名来实现。这样做的好处是,可以避免全局 CSS 污染和类名冲突,特别是在大型项目中使用时,非常有用。
- 当
- **不设置
modules: true**:- 如果没有设置
modules: true,则css-loader不会进行类名的局部作用域化处理,而是保留原始的 CSS 类名,直接应用到页面中。这种情况下,所有的 CSS 类名都是全局有效的,可能会导致命名冲突和不可预测的样式覆盖问题,特别是在复杂的应用中。
- 如果没有设置
因此,是否设置 modules: true 取决于你的项目需求和管理风格。对于大多数现代项目,特别是使用模块化开发的情况下,推荐设置 modules: true 来保持 CSS 的模块化管理,提高代码的可维护性和安全性。
配置插件(plugin)
想要使用一个插件,你只需要
require()它,然后把它添加到plugins数组中。多数插件可以通过选项(option)自定义。你也可以在一个配置文件中因为不同目的而多次使用同一个插件,这时需要通过使用new操作符来创建一个插件实例。
下载 html-webpack-plugin
1 | npm install html-webpack-plugin -D |
示例中,html-webpack-plugin 为应用程序生成一个 HTML 文件,名为indexdist.html,并自动将生成的所有 bundle 注入到此文件中。template是将已经好的文件也打包过去
webpack.config.js
1 | const path = require('path'); |
提醒:Webpack的配置对象中,
plugins应该是直接放在配置对象的顶层,而不是放在module下面。
配置模式(mode)
通过选择 development, production 或 none 之中的一个,来设置 mode 参数,你可以启用 webpack 内置在相应环境下的优化。其默认值为 production。
1 | module.exports = { |
支持以下字符串值:
| 选项 | 描述 |
|---|---|
development |
会将 DefinePlugin 中 process.env.NODE_ENV 的值设置为 development. 为模块和 chunk 启用有效的名。 |
production |
会将 DefinePlugin 中 process.env.NODE_ENV 的值设置为 production。为模块和 chunk 启用确定性的混淆名称, |
none |
不使用任何默认优化选项 |
配置热更新热加载
每次都需要bulid非常麻烦,webpack提供了一个watch命令,可以帮助我们热编译,
1 | "scripts": { |
但是,这个办法,还是每次都需要刷新才可以看到效果,这就需要webpack的模块热替换(hot module replacement)具体参考:https://webpack.docschina.org/concepts/hot-module-replacement/
根据官方的文档:
在开发环境,可以将 HMR 作为 LiveReload 的替代。webpack-dev-server 支持
hot模式,在试图重新加载整个页面之前,hot模式会尝试使用 HMR 来更新。更多细节请查看 模块热替换 指南。
我们要下载webpack-dev-server:
1 | npm install webpack-dev-server -D |
webpack.config.js
1 | const path = require('path'); |
这个代码中需要把filename: 'index.html',改成index.html.
增加配置:
1 | devServer: { |
