前言
看了很多webpack相关文章,一直读不进去(或者记不住),无非将webpack官文档的配置说明,重新梳理下顺序或者翻译不好部分的再重新处理一下。很少以项目角度去讨论一个webpack工程项目如何从0到1搭建,搭建完成之后随着项目的复杂度提高又是如何一步步优化,达到最佳实践过程。
本系列是基于以下webpack版本来展开的讨论的
"webpack": "^4.46.0",
"webpack-dev-server": "^3.11.2"
【一】 项目初始化
新建一个文件夹webpack-demo
,执行下面命令。
npm init -y
npm install webpack webpack-cli -D
【二】 配置打包的输入(entry)与输出(output)
在src/index.js
路径下写点代码,配置webpack.config.js
module.exports = {
entry:'./src/index.js', // 输入输出
output: {
path: path.resolve(__dirname, "./dist"), // 打包后的目录
filename:"bundle.js"
}
}
【三】 配置构建命令
1、 在 package.json scripts 添加构建打包命令
scripts:{
"build": "webpack --config webpack.config.js"
}
2、验证:
终端执行打包命令npm run build
将会在dist目录下生成一个bundle.js文件。
【四】自动引入打包生成的文件bundle.js
- 安装依赖:
html-webpack-plugin
和clean-webpack-plugin
npm i -D html-webpack-plugin clean-webpack-plugin
- 配置 webpack.config.js,以插件形式引入
const HtmlWebpackPlugin = require("html-webpack-plugin");
const { CleanWebpackPlugin } = require("clean-webpack-plugin");
module.exports = {
// ... 省略其它配置项目
plugins:[
new CleanWebpackPlugin({ // 每次打包前清空打包输出目录
// cleanOnceBeforeBuildPatterns:['**/*', '!dll', '!dll/**'] // 不删除dll目录下的文件
}), // 清空打包输出目录
new HtmlWebpackPlugin({
template: './index.html' // 源模板文件
// filename: './index.html' // 指定输出文件
})
]
}
验证:
终端执行命令npm run build
将打包dist生成文件除了bundle.js,还有index.html 。这样打包之后bundle.js自动注入到index.html
【五】搭建本地服务器
- 安装依赖
webpack-dev-server
npm i -D webpack-dev-server
2、配合服务启动目录、端口
module.exports = {
// ... 省略其它配置项目
devServer: {
port: 3001,
hot: true,
contentBase: "./dist",
}
}
- 在 package.json scripts 配置本地服务启动命令
scripts:{
"serve": "webpack-dev-server --config webpack.config.js --open"
}
4、验证:
在终端执行npm run serve
,会自动开口浏览器启动本地服务
【六】 配置解析和转换文件的策略 module
常见loader
loder | 功能 | babel-loader | 解析 .js 和 .jsx 文件 | tsx-loader | 处理 ts 文件 | less-loader | 处理 less 文件,并将其编译为 css | sass-loader | 处理 sass、scss 文件,并将其编译为 css | css-loader | 处理 css 文件 | style-loader | 将 css 注入到 DOM | file-loader | 将文件上的import / require 解析为 url,并将该文件输出到输出目录中 | url-loader | 用于将文件转换成 base64 uri 的 webpack 加载程序 | html-loader | 将 HTML 导出为字符串, 当编译器要求时,将 HTML 最小化 |
---|
6.1 处理js(引入babel-loader)
由于不同浏览器对高级语法的支持性并不是非常好,为了向下兼容考虑将他们转换为ES5标准
- 安装依赖
babel-loader
()、@babel/core
和@babel/preset-env
npm install -D babel-loader @babel/core @babel/preset-env
- 配置
webpack.config.js
module.exports={
module:{
{
test: /\.js$/,
loader: 'babel-loader',
exclude: /node_modules/ //
}
}
}
- 根目录新建.babelrc
{
"presets": [
"@babel/preset-env" // 官方推荐使用,包含了所有现代js(es2015 es2016等)的所有新特性
]
}
- 如果你希望 加入懒加载 TODO
npm i -D @babel/plugin-syntax-dynamic-import
同时更新 .babelrc 文件,加入plugins配置
{
"presets": [
"@babel/preset-env"
],
"plugins": [
"syntax-dynamic-import"
]
}
验证:
在index.js 加入箭头函数,执行构建命令查看bundle.js
是否将ES6箭头函数转换为普通函数
// Babel Input: ES2015 arrow function
[1, 2, 3].map((n) => n + 1);
// Babel Output: ES5 equivalent
[1, 2, 3].map(function(n) {
return n + 1;
});
6.2 处理css(scss less),这里以scss举例
- 为支持css import,安装依赖
style-loader css-loader
npm i -D style-loader css-loader
- 如果我们使用sass来构建样式,则需要多安装两个node-sass sass-loader
npm i -D node-sass sass-loader
3、为css增加浏览器前缀
npm i -D postcss-loader autoprefixer
3、配置 webpack.config.js,通过loader形式让webpack 知道以何种loader加载对应后缀名(.css
和scss
)的文件,从而打包进bundle.js
module.exports = {
// ... 省略其它配置项目
module:{
rules:[
{
test:/\.css$/,
use:['style-loader','css-loader'] // 从右向左解析原则
},
{
test:/\.scss$/,
use:['style-loader','css-loader','postcss-loader','sass-loader'] // 从右向左解析原则
}
]
}
}
4、验证:
新建一个.sccs文件,写一些sass 语法样式,以及css3语法,查看实际输出结果
// 变量定义
$color: blue;
body {
/*嵌套*/
.test {
height: 100px;
display: flex;
align-items: center;
justify-content: center;
background-color: $color;
color: #fff;
}
}
6.3 处理图片/字体等多媒体文件
- 为支持import 字体、图片等其它多媒体格式文件,安装依赖
url-loader file-loader
npm i -D url-loader file-loader
- 配置 webpack.config.js,通过loader形式让webpack知道以何种loader加载这些多媒体格式文件的
注意:url-loader
一般与file-loader
搭配使用,功能与file-loader
类似,如果文件小于限制的大小。则会返回base64
编码,否则使用 file-loader
将文件移动到输出的目录中
module.exports = {
// ... 省略其它配置
module:{
rules:{
{
test: /\.(jpe?g|png|gif)$/i, //图片文件
use: [
{
loader: 'url-loader',
options: {
limit: 10240,
fallback: {
loader: 'file-loader',
options: {
name: 'img/[name].[hash:8].[ext]'
}
}
}
}
]
},
{
test: /\.(mp4|webm|ogg|mp3|wav|flac|aac)(\?.*)?$/, //媒体文件
use: [
{
loader: 'url-loader',
options: {
limit: 10240,
fallback: {
loader: 'file-loader',
options: {
name: 'media/[name].[hash:8].[ext]'
}
}
}
}
]
},
{
test: /\.(woff2?|eot|ttf|otf)(\?.*)?$/i, // 字体
use: [
{
loader: 'url-loader',
options: {
limit: 10240,
fallback: {
loader: 'file-loader',
options: {
name: 'fonts/[name].[hash:8].[ext]'
}
}
}
}
]
},
]
}
}
}
【七】】其它
7.1 mode
mode 配置选项告用于告诉webpack相应地使用其内置的优化。可选配置有 development
、production
或 none
,具体可查看官方文档
7.2 devtool
在了解Source Map用处之后,你就会容易理解通过devtool的配置 webpack 如何生成 Source Map,用来增强调试过程。不同的值会明显影响到构建(build)和重新构建(rebuild)的速度。
生产环境(mode=production)
:默认为 null ,一般不设置( none )或 nosources-source-map开发环境(mode=development)
:默认为 eval ,一般设置为 eval、cheap-eval-source-map 、cheap-module-eval-source-map
sourcemap 生成几个策略:
值 | 原理 | 优缺点 | eval | 通过eval包裹每一个module模块,编译后不会生成sourcemap 文件,仅仅是在每一个模块后,增加sourceURL来关联模块处理前后对应的关系 | 优点是:打包速度非常快,因为不需要生成sourcemap文件。缺点是:由于会映射到转换后的代码,而不是映射到原始代码,所以不能正确的显示行数。 | source-map | 为每一个打包后的模块生成独立的sourcemap文件,打包后的代码最后面一句代码是 // #sourceMappingURL=bundle.js.map ,同时在dist目录下会针对每一个模块生成响应的 .map文件 | 拥有完整的源代码信息,便于调试,但影响持续构建 | inline | 不会生成独立的 .map文件,而是将.map 文件以dataURL的形式插入 | 缺点:打包输出文件变大 | cheap | 打包后同样会为每一个文件模块生成 .map 文件,但是与source-map 的区别在于cheap-source-map 生成的 map文件会忽略原始代码中的列信息 | 可以大幅提高souremap 生成的效率,但没有列信息(会映射到转换后的代码,而不是映射到原始代码),通常我们调试并不关心列信息 | module | 同样生成一个没有列的信息的sourcemap文件,同时loader的sourcemap也被简化成为只包含对应行 | 支持babel 这种预编译工具,找到最初源码信息 |
---|
如何根据不同环境选择相应sourceMap 生成策略?
-
- 源代码中的列信息是没有任何作用,因此我们打包后的文件不希望包含列相关信息,只有行信息能建立打包前后的依赖关系。因此不管是开发环境或生产环境,我们都希望添加
cheap
的基本类型来忽略打包前后的列信息。
- 源代码中的列信息是没有任何作用,因此我们打包后的文件不希望包含列相关信息,只有行信息能建立打包前后的依赖关系。因此不管是开发环境或生产环境,我们都希望添加
-
- 不管是开发环境还是正式环境,我们都希望能定位到bug的源代码具体的位置,比如说某个vue文件报错了,我们希望能定位到具体的vue文件,因此我们也需要module配置。
-
- 我们需要生成map文件的形式,因此我们需要增加
source-map
属性。
- 我们需要生成map文件的形式,因此我们需要增加
-
- 我们介绍了eval打包代码的时候,知道eval打包后的速度非常快,因为它不生成map文件,但是可以对eval组合使用
eval-source-map
使用会将map文件以DataURL的形式存在打包后的js文件中
- 我们介绍了eval打包代码的时候,知道eval打包后的速度非常快,因为它不生成map文件,但是可以对eval组合使用
因此建议:
// 在开发环境中我们可以使用 , eval加快打包效率
module.exports = {
devtool: 'cheap-module-eval-source-map'
}
// 在正式环境中我们可以使用
module.exports = {
devtool: 'cheap-module-source-map';
}
常见问题FAQ
- 免费下载或者VIP会员专享资源能否直接商用?
- 本站所有资源版权均属于原作者所有,这里所提供资源均只能用于参考学习用,请勿直接商用。若由于商用引起版权纠纷,一切责任均由使用者承担。更多说明请参考 VIP介绍。
- 提示下载完但解压或打开不了?
- 找不到素材资源介绍文章里的示例图片?
- 模板不会安装或需要功能定制以及二次开发?
发表评论
还没有评论,快来抢沙发吧!