Appearance
Compiler 对象包含了Webpack环境所有的配置信息,包含options, loader, plugins 这些信息, 这个对象在Webpack 启动时候被实例化,它是全局唯一的。
Compilation 对象包含了当前的模块资源、编译生成资源、变化的文件等。当Webpack 已开发模式运行时,每当检测到一个文件变化,一次新的Compilation 将被创建。
Compiler 和 Compilation 的区别在于:Compiler 代表了整个Webpack从启动到关闭的生命周期, 而Compilation 只是代表了一次新的编译。
提取vendor
假如工程只生成一个JS文件并且它的体积很大,一旦产生代码更新,即便只有一点点改动,用户都要重新下载整个资源文件,这对于页面的性能是非常不友好的。
为了解决这个问题,我们可以使用提取vendor的方法。vendor的字面意思是“供应商”,在Webpack中则一般指工程所使用的库、框架等第三方模块集中打包而产生的bundle。
module.exports = { context: path.join(__dirname, './src'), entry: { app: './src/app.js', vendor: ['react', 'react-dom', 'react-router'], }, };
在上面的配置中,app.js仍然和最开始一样,其内容也不需要做任何改变,只是我们添加了一个新的chunk name为vendor的入口,并通过数组的形式把工程所依赖的第三方模块放了进去
babel-loader
由于@babel/preset-env会将ES6 Module转化为CommonJS的形式,这会导致Webpack中的tree-shaking特性失效。将@babel/preset-env的modules配置项设置为false会禁用模块语句的转化,而将ES6 Module的语法交给Webpack本身处理。babel-loader支持从.babelrc文件读取Babel配置,因此可以将presets和plugins从Webpack配置文件中提取出来,效果是相同的
cacheDirectory: 会启用缓存机制,在重复打包未改变过的模块时防止二次编译,加快打包的速度。cacheDirectory可以接收一个字符串类型的路径来作为缓存路径,这个值也可以为true,此时其缓存目录会指向node_modules/.cache/babel-loader。
file-loader
- file-loader用于打包文件类型的资源,并返回其publicPath。
Webpack 5也提供了另一种方式(asset/resource)来处理文件类型资源,可以用来替代file-loader。并且这种方式是内置的,使用起来更加便捷:
rules: [
{
test: /\.(png|jpg|gif)$/,
type: 'asset/resource'
}
]
url-loader
Webpack 5也提供了内置的解决方案,可以替代url-loader来处理inline类型的资源。
url-loader的作用与file-loader类似,唯一的不同在于,url-loader允许用户设置一个文件大小的阈值,当大于该阈值时它会与file-loader一样返回publicPath,而小于该阈值时则返回base64形式的编码。
rules: [
{
test: /\.svg$/,
type: 'asset/inline'
}
]
- [name] 指的是chunk 的名字
source-map
- source-map安全
source-map不仅可以帮助开发者调试源码,当线上出现问题时也有助于查看调用栈信息,是线上查错十分重要的线索。同时,有了source-map也就意味着任何人通过浏览器的开发者工具都可以看到工程源码,对于安全性来说也是极大的隐患。那么如何才能在保持其功能的同时,防止暴露源码给用户呢?
Webpack提供了hidden-source-map及nosources-source-map两种策略来提升source-map的安全性。hidden-source-map意味着Webpack仍然会产出完整的map文件,只不过不会在bundle文件中添加对于map文件的引用。这样一来,当打开浏览器的开发者工具时,我们是看不到map文件的,浏览器自然也无法对bundle进行解析。如果我们想要追溯源码,则要将map文件上传到第三方服务上实现。目前最流行的解决方案是Sentry。
Sentry是一个错误跟踪平台,可以使开发者接入后进行错误的收集和聚类,以便于更好地发现和解决线上问题。Sentry支持JavaScript的source-map,我们可以通过它所提供的命令行工具或者Webpack插件来自动上传map文件。同时我们还要在工程代码中添加Sentry对应的工具包,这样每当JavaScript执行出错时就会上报给Sentry。Sentry在接收到错误后,就会去找对应的map文件进行源码解析,并给出源码中的错误栈。
另一种配置是nosources-source-map,它对于安全性的保护则没那么强,但是使用方式相对简单。打包部署之后,我们可以在浏览器开发者工具的Sources选项卡中看到源码的目录结构,但是文件的具体内容会被隐藏起来。对于错误来说,我们仍然可以在Console控制台中查看源代码的错误栈,或者console日志的准确行数。它对于追溯错误来说基本足够,并且安全性相对于可以看到整个源码的source-map配置来说要略高一些。
除了通过上述介绍的这些配置提高安全性,我们也可以正常打包出source-map,然后通过服务器的Nginx设置(或其他类似工具)将.map文件只对固定的白名单(比如公司内网)开放,这样我们仍然能看到源码,而在一般用户的浏览器中就无法获取到它们了。
externals
/* * key: package.json的第三方依赖库名称 * value: 第三方依赖编译打包后生成的js文件,然后js文件执行后赋值给window的全局变量名称 */ externals:{ key: value }