问题一:webpack是什么?
webpack是一个前端资源加载/打包工具。它将根据模块的依赖关系进行静态分析,然后将这些模块按照指定的规则生成对应的静态资源。
问题二:webpack四个核心概念
入口(entry)
- webpack打包的起点,一个或多个(一般是JS文件)
- webpack会从起点文件开始,寻找起点直接或间接依赖的其他所有依赖,包括JS、CSS、图片资源等作为将来打包的原始数据。
【单入口】
entry: './src/index.js'
// vuewebpack的配置
const path = require('path')
module.exports = {
entry: path.join(__dirname, 'src', 'index.js') // __dirname;表示webpack.config.js所在的目录
}
// 打包形成一个chunk,输出一个bundle文件,此时chunk的名称默认为main
【多入口】
// array
entry: ['.src/index.js', './src/add.js']
// 所有的文件最终只会形成一个chunk,输出只有一个bundle文件,此时chunk的名称默认为main(会将add.js打包进index.js中)
// object
entry: {
index: './src/index.js',
add: './src/add.js'
}
// 有几个入口文件就形成几个chunk,并输出几个bundle文件。chunk的名称是key(index、add...)
出口(output)
- 告诉webpack在哪里输出它所创建的bundles(
path: path.join(__dirname, 'dist')),以及如何命名这些文件(filename: 'bundle.js')。
const path = require('path');
module.exports = {
output: {
path: path.resolve(__dirname, 'dist'),
filename: 'bundle.js'
// filename: '[name].js' // 针对多个入口起点。使用占位符(substitutions)来确保每个文件具有唯一的名称
}
}
加载器(loader)
- webpack只识别JS文件。若加载非JS文件,必须指定一些额外的加载器(loader),如
css-loader/style-loader。 - loader能将所有类型的文件转换为webpack能够处理的有效模块。
// test属性:用于标识出应该被对应的loader进行转换的某个或某些文件。
// use属性:表示进行转换时,应该使用哪个loader。
const path = require('path');
module.exports = {
module: {
rules: [
{test: /\.css$/, use: 'css-loader'}
]
}
}
// “嘿,webpack 编译器,当你碰到「在 `require()`/`import` 语句中被解析为 '.css' 的路径」时,在你对它打包之前,先使用 `css-loader` 转换一下”
使用loader: www.webpackjs.com/concepts/lo…
插件(plugins)
- 扩展webpack的功能,让webpack不仅仅完成打包,甚至各种更复杂的功能。
- 如果要使用插件,只需要
require()它,然后添加到plugins数组中。也可以在一个配置文件中因为不同目的而多次使用同一个插件,这时需要通过使用new操作符来创建它的一个实例。
const HtmlWebpackPlugin = require('html-webpack-lugin') // 通过npm安装 - npm install html-webpack-plugin --save-d
module.export = {
plugins: [
new HtmlWebpackPlugin({
template: path.join(__dirname, 'src', 'index.html'), // 以src->index.html文件为模板进行打包
filename: 'index.html'
})
],
}
// htmlWebpackPlugin实现将打包好的.js文件自动载入我们的.html文件
参考:www.webpackjs.com(webpack中文文档)
webpack的工作原理
webpack可以看做是模块打包机:分析项目结构,找到Javascript模块以及其他的一些浏览器不能直接运行的拓展语言(Scss、TS等),并将其转换和打包为合适的格式供浏览器使用。
webpack打包原理
把一切都视为模块:不管是css、js、image还是html都可以互相引用。通过定义entry,对所有依赖的文件进行跟踪,将各个模块通过loader和plugins处理,让然后打包在一起。
// 模块的引用
ES6 : import
commonJS : require()
AMD : define 和 require
css/sass/less : @import
按需加载:打包过程中webpack通过Code Splitting功能将文件分为多个chunks,还可以将重复部分单独提取出来作为commonChunk,从而实现按需加载。把所有依赖打包成一个bundle.js文件,通过代码分割成单元片段按需加载。
webpack基本功能
- 代码转换:TS->JS、SCSS->CSS ...
- 文件优化:压缩JS、CSS、HTML代码,压缩合并图片
- 代码分割:提取多个页面的公共代码,提取首屏不需要执行的部分代码让其异步加载
- 模块合并:在采用模块化的项目中有很多模块和文件,需要构建功能把模块分类合并成一个文件
- 自动刷新:监听本地源代码的变化,自动构建,刷新浏览器(插件 - webpack-dev-server)
- 代码校验:在代码被提交到仓库前需要检测代码是否符合规范,以及单元测试是否通过
gulp/grunt 与webpack的区别
- 三者都是前端构建工具。
- gulp处理轻量级的任务(如单独打包CSS文件)
- webpack是基于入口的,自动递归解析入口所需要的所有资源文件,使用plugin扩展webpack功能
如何提高webpack构架速度
- 多入口情况下,使用CommonesChunkPlugin来提取公共代码
- 通过externals配置来提取常用库
- 利用DllPlugin和DllReferencePlugin预编译资源模块
- 使用Happypack实现多线程加速
- 使用webpack-uglify-paralle提升uglifyPlugin的压缩速度
- 原理上webpack-uglify-parallel采用了多核并行压缩来提升压缩速度使用Tree-shaking和Scope Hoisting来剔除多余代码
前端打包和构建的目的
- 代码层面
- 体积更小(Tree-shaking、压缩、合并),加载更快
- 编译高级语言和语法(TS、ES6、SCSS、模块化)
- 兼容性和错误检查(polyfill、postcss、eslint)
- 研发流程层面
- 统一、高效的开发环境
- 同意的构建流程和产出标准
- 继承公司构建规范
webpack构建流程
- 初始化参数:从配置文件和Shell语句中读取与合并参数,得出最终的参数;
- 开始编译:用上一步的参数初始化Complier对象,加载所有配置的插件,执行对象的run方法开始执行编译;
- 确定入口:根据entry找出所有的入口文件;
- 编译模块: 从入口文件出发,调用所有配置的Loader对模块进行编译,再找出该模块依赖的模块,再递归本步骤直到所有入口的依赖文件都经过本步骤的处理;
- 完成模块的编译:经过上一步使用Loader编译完所有模块后,得到了每个模块被编译后的最终内容以及它们之间的依赖关系;
- 输出资源:根据入口和模块之间的依赖关系,组装成一个个包含多个模块的Chunk,再把每个Chunk转换成一个单独的文件加入到输出列表;
- 输出完成:在确定好输出内容后,根据配置确定输出的路径和文件名,把文件内容写入到文件系统。
loader机制的作用
webpack默认只能打包js文件,配置里的module.rules数组配置了一组规则,告诉 Webpack 在遇到哪些文件时使用哪些 Loader 去加载和转换打包成js。
plugin插件的作用
Plugin 是用来扩展 Webpack 功能的,通过在构建流程里注入钩子实现,它给 Webpack 带来了很大的灵活性。
Webpack 是通过plugins属性来配置需要使用的插件列表的。plugins属性是一个数组,里面的每一项都是插件的一个实例,在实例化一个组件时可以通过构造函数传入这个组件支持的配置属性。
bundle/ chunk/ module
bundle: 是由webpack打包出来的文件
chunk:是指webpack在进行模块依赖分析时,代码分割出来的代码块
module:开发中的单个模块
模块热更新(hot module replacement - HMR)
模块热更新是webpack的一个功能,可以是的代码修改之后,不用刷新浏览器就可以更新。
Webpack-dev-server(重加载) + HotModuleReplacementPlugin(局部更新)
Tree-sharking
定义
值打包中去除那些引入了但在代码中没用到的死代码(dead-code)
发生的时期
发生在webpack将chunk(代码块)打包成bundle(打包后的文件)的阶段。
在把一个个块打包在一起的过程中,需要把无用的代码清除,来达到优化打包文件大小的目的。