这是我参与「第四届青训营 」笔记创作活动的的第4天。
进阶中高级前端工程师,对webpack打包构建工具的掌握是必不可少的。我也曾经看过许多webpack教程,但无非是记记某些模式怎么配置,根本就没有认识到webpack的魅力,借此次青训营的机会,希望范文杰老师能给我带来不一样的收获。如果你也想了解的话,不妨接着看下去。
我们总是听说前端要具备工程化思维,那到底什么是工程化思维呢?这里我给出一段从知乎上摘抄的定义,
狭义上的理解:将开发阶段的代码发布到生产环境,包含:构建,分支管理,自动化测试,部署
广义上理解:前端工程化应该包含从编码开始到发布,运行和维护阶段
一、什么是webpack?
前端项目是由很多资源文件组合而成,为了保证代码的正确运行,要考虑文件之间的引用关系,必须严格按照依赖顺序书写代码,除此之外,还有很多其他问题,大大影响开发效率。
为了解决这些问题,市面上出现了很多工具,如gulp、rollup、vite等,其中目前最具影响力、应用最为广泛的当属webpack。
webpack本质上是一种前端资源编译、打包工具。
二、使用webpack
示例
1、安装
npm i -D webpack webpack-cli
2、编辑配置文件——webpack.config.js
const path = require('path')
module.exports = {
entry: './src/index',
mode: 'development',
devtool: false,
output: {
filename: `[name].js`,
path: path.join(__dirname, './dist')
}
}
我来解释一下上面导出内容是什么意思:entry是打包的入口文件,mode则是打包模式,一般会有开发环境和生产环境的区别,
output则是出口文件,用于指定文件打包后的位置
3、执行编译命令
npx webpack
三、webpack打包的核心流程——极度简化版
- 入口处理——从’entry’文件开始,启动编译流程
- 依赖解析——从’entry’文件开始,根据’require’ or 'import’等语句找到依赖资源
- 资源解析——根据’module’配置,调用资源转移器,将png、css等非标准js资源转译成js内容
- 资源合并打包——将转译后的资源内容合并打包为可直接在浏览器运行的js文件
四、使用webpack
关于webpack的使用方法,基本都围绕“配置”展开,而这些配置大致可划分为两类:
——流程类:作用于流程中某个或若干个环节,直接影响打包效果的配置项
——工具类:主流程之外,提供更多工程化能力的配置项
1、处理js文件
其实处理使用es6之前的语法编写的js文件是不需要额外安装插件的,其配置文件和上面代码并无二致。
2、处理css文件
首先在入口文件引入对css依赖,
import './index.css'
console.log("hello world")
然后再通过npm安装对应的loader
npm i style-loader css-loader
配置webpack文件
const path = require('path')
module.exports = {
entry: './src/index',
mode: 'development',
devtool: false,
output: {
filename: `[name].js`,
path: path.join(__dirname, './dist')
},
module: {
rules: [{
test: /\.css$/,
use: ['style-loader', 'css-loader']
}]
}
}
第一次看到这段代码你可能会有点懵,我来帮你解释一下。
rules中的test后面跟的是一个正则表达式,上述正则表达式含义是匹配以.css结尾的文件,
use后面跟着的则是对应使用的loader去处理文件
3、处理es6+代码
如上面所说,处理es6之前的代码是无需下载其它loader的,基本所有的浏览器都提供对es5的支持,为了让开发者能享受到新语法的简便同时兼顾对其它浏览器的兼容,babel这个插件就大放异彩。
再入口文件书写es6代码
class Person {
constructor() {
this.name = 'ExMaterial'
}
}
console.log((new Person()).name)
const say = () => {}
然后再通过npm安装对应的loader
npm i -D @babel/core @babel/preset-env babel-loader
配置文件
const path = require('path')
module.exports = {
entry: './src/index',
mode: 'development',
devtool: false,
output: {
filename: `[name].js`,
path: path.join(__dirname, './dist')
},
module: {
rules: [{
test: /\.js$/,
use: [{
loader: 'babel-loader',
options: {
presets: [
['@babel/preset-env']
]
}
}]
}]
}
}
4、处理html
处理html就不像上述代码是再module中继续使用loader,而是要用到一个新的配置项——plugins。
webpack官网对plugins的解释是——While loaders are used to transform certain types of modules, plugins can be leveraged to perform a wider range of tasks like bundle optimization, asset management and injection of environment variables.(虽然loaders用于转换某些类型的模块,但是插件可以用来执行更广泛的任务,如捆绑包优化、资源管理和环境变量注入。)
这里给出官网的一段配置代码:
const HtmlWebpackPlugin = require('html-webpack-plugin');
const webpack = require('webpack'); //to access built-in plugins
module.exports = {
module: {
rules: [{ test: /\.txt$/, use: 'raw-loader' }],
},
plugins: [new HtmlWebpackPlugin({ template: './src/index.html' })],
};
————————————————————分割线————————————————————
聊了上面那些东西后,再来说一点其它类似“黑科技”的配置
1、HMR-Hot Module Replacement-模块热替换
何为热替换,即你修改代码后,页面会自动刷新,而无需开发者手动刷新,现在前端各种框架的脚手架同理。
其实webpack已经内置这个功能了,要开启只需要自己在webpack.config.js中配置一下就好了
module.exports = {
// ...
devServer: {
hot: true
}
};
2、Tree-Shaking-树摇
用于删除没有用到的代码,减小打包后的体积
module.exports = {
// ...
mode: "production",
optimization.usedExports: true
};
此外,还有很多其它工具:
- 缓存
- Sourcemap
- 性能监控
- 日志
- 代码压缩
- 分包
- …
进阶篇plugins的内容就不写了,那么今天的分享就到此结束了。