前言
如果你是一个初级前端,想往中级前端走,webpack是一个必要掌握的技能,只有了解了它才能慢慢的体会的工程化的含义。
什么是工程化
在过去时代,页面没法做到很复杂的原因之一是,js代码一多起来,会出现各种命名冲突的问题,哪个js文件先引入,哪个后引入,特别难判断。你想想看一个html文件几十个script文件的引入,头就大了。
当工程化时代来临后,通过模块化的导入导出关系,js变量的使用变得井然有序,例如a引用b,b引用c,b命名了a中的同名变量,两者相互隔离,互不影响。那么我们只需要在开发环境中,引入一个index.js
,剩下的通过模块的引用关系,让整个程序运行起来即可。
当模块化思想步入主流后,第三方库也随之兴起,这时会发现,第三方库内部也会引入其他的第三方小库,而且每个第三方库引入的小库版本可能还是不一样的,当项目引入的三方库一多起来,也特别的乱,文件不好管理。
这个时候包管理也加入了工程化里头,也就是咋们常用的npm管理,通过简单的按照卸载指令就可以轻松的管理第三方库。
工程化还带来了很多便利,框架也是因为工程化的发展而兴起的,目前主流搭建工程化项目的工具是webpack,也是这次我们要学习的东西。
什么是webpack
是一个构建工具
集合了很多功能:
- js高级语法转换;
- 转换JSX、vue的指令等;
- css兼容转换,预处理器编译;
- 压缩混淆;
- 图片压缩;
- 等等
所以叫构建工具。
是一个静态模块打包工具
直接上官网的一张图
webpack通过一个文件(或者多个)作为入口——例如vue中的main.js,将该文件层层的引用依赖(js、css、等静态文件)关系生成一个树结构,每个节点都看成是一个模块module,再将有引用关系的树枝处理成一个chunk(块),在块中再进行一些想要的处理例如js降级编译、做加密等处理,最终打包成一个或多个文件bundle。
在上面的解释中提到几个webpack的重要概念:
- module:在webpack眼里,一切文件的引入都看成模块,多个模块在webpack处理过程中打包成一个chunk。
- chunk:可以理解为多个module打包后的js文件,例如我们的入口文件、抽离文件、异步加载文件(后面会解释这些是什么)。这个chunk是webpack的处理阶段产生的。module与chunk之间的关系可能是多对一的。
- bundle:最终chunk打包出来的多个文件叫bundle。chunk与bundle之间可能是一对多的关系。
所以,webpack打包的过程可以简单的理解为从module到chunk到bundle的一个过程。
安装
同时安装webpack和它的cli。
npm i -g webpack webpack-cli --save-dev
查看版本
webpack -v
体验
先初始化一个node项目,生成package.json文件。
npm init -y // y表示默认配置为yes
JS打包
创建src文件夹,里面放一个主入口文件main.js和两个要引入进主入口文件的js文件,例如a.js与b.js:
a:
function a(n) {
document.write("这是a文件")
}
module.exports = {
a,
}
b:
function b(n) {
document.write("这是b文件")
}
module.exports = {
b,
}
main.js:
//把js模块进行集中引入
const a = require('./a.js')
const b = require('./b.js')
a.a()
b.b()
然后建立个webpack.cofig.js文件配置打包规则(注意,由于webpack是在node环境中运行,所以要使用common.js的规范):
const path = require('path') // 导入node自带的path模块
// 定义JS的打包规则
module.exports = {
mode: 'development', // mode决定优化的模式,none不优化,development开发者模式,帮助输出调试信息,production生产模式,最高优化,启用压缩,忽略错误。
entry: './src/main.js', // 入口函数从哪里开始进行编译打包
output: { // 编译完后输出设置
path: path.resolve(__dirname, './dest'), // 输出文件,__dirname表示当前文件的目录绝对路径,第二个参数表示文件名
filename: 'bundle.js' // 生成的文件名
}
}
完事后执行
webpack
webpack -w 表示自动监听到代码更新后,自动重新打包。
就会看见生成了打包文件夹,里面的文件是代码加密过的,是把a.js、b.js、main.js之间的导入关系看成是个整体打包成了一个js文件,这个js文件用script标签去引入能正常使用。
那css文件怎么打包?
css打包
首先要安装css的打包依赖:
npm install --save-dev style-loader css-loader
webpack.cofig.js配置打包规则:
const path = require('path')
module.exports = {
mode: 'development',
entry: './src/main.js',
output: {
path: path.resolve(__dirname, './dest'),
filename: 'bundle.js'
},
module: {
rules:[{
test: /\.css$/, // 把所有css文件打包
use: ['style-loader', 'css-loader'] // 使用的依赖
}]
}
}
入口文件main.js,把css模块进行集中引入
require('./c.css')
执行webpack指令,生成打包文件,不过我去看的时候居然没看见css文件,莫非是写进生成的js文件中了?真是神奇哈哈。
如果有多个入口文件呢?
加配置:
const path = require('path')
module.exports = {
mode: 'development',
entry: { // 这里多加入口
'./src/main.js',
'./src/login.js'
},
output: {
path: path.resolve(__dirname, './dest'),
filename: '[name].js' // 以入口文件命名作为区分
}
}
通过npmscript运行
可以在package.json中添加一个脚本指令:
"scripts": {
"build": "webpack",
}
为何需要构建化打包
从代码层面
- 打包后的代码体积更小(tree-shaking、压缩、合并),浏览器加载更快,用户体验更好
- 能够编译高级语言或语法(TS,ES6+,模块化,scss),让老旧浏览器都能运行
- 兼容性和错误检查(polyfill、postcss、eslint),减少代码运行错误
从项目层面
- 让整个开发团队都是在一样的开发环境中进行,不用自己再去单独设置,提高开发效率
- 每个人的生产打包构建都是一样的,都完全按照预设的标准来
- 能够集成公司构建规范(提测、上线等)
是前端发展的历史所趋
尾巴
第一章只是先体验一下webpack是个什么东西,如何简单的进行使用。后续会稍微展开去做记录。