Webpack构建项目进一步优化
2021-04-19 10:29
标签:html web 之间 代码 有用 更新 dirname get config 操作系统 webpack在打包后,生成的文件主要分为三种类型: * 业务代码 * 外部依赖库 * webpack runtime webpack中的dll和external在本质上其实是解决的同一个问题:避免将某些外部依赖库打包进我们的业务代码,而是在运行时提供这些依赖。 一方面实现了代码拆分,以及依赖的复用,另一方面提升构建速度. 这两种方案应该是各有各的优劣,分别适用于不同的环境。 dll 符合前端模块化的要求 webpack配置上稍微复杂一些,需要预打包所需的dll资源,并在构建时配置相应的plugin, 使用dll的前提是,这些外部依赖一般不需要发生变更。所以,如果某天发生了变更,那就需要将项目重新构建,违背了dll的使用前提,必然要作出相应的牺牲。 external不太符合前端的模块化思想,所需要的外部库需要在浏览器全局环境下可访问 外部库升级的话,如果兼容之前的API,不需要项目重新构建 webpack配置上稍微简单些,但是同样需要将所需的外部库打包为所需要的格式,并在运行态下引用 相比较而言的话,dll比external应该更加智能一些,主要体现在模块的引用和打包上。比如说如下方式去引用了react中的一个方法: import AA from ‘react/lib/createClass‘ 如果采用dll的方式,是不会造成重复打包的,他会将引用直接指向dll。但是如果使用external的话,则会react中的部分代码打包进来。 防止将某些 import 的包(package)打包到 bundle 中,而是在运行时(runtime)再去从外部获取这些扩展依赖(external dependencies)。 例如,从 CDN 引入 jQuery,而不是把它打包 module.exports = { //... externals: { jquery: ‘jQuery‘ }}; 这样就剥离了那些不需要改动的依赖模块,换句话,下面展示的代码还可以正常运行: import $ from ‘jquery‘; $(‘.my-element‘).animate(/* ... */); DLLPlugin为什么会出现? 在使用webpack进行打包时候,对于依赖的第三方库,比如vue,vuex等这些不会修改的依赖,我们可以让它和我们自己编写的代码分开打包,这样做的好处是每次更改我本地代码的文件的时候,webpack只需要打包我项目本身的文件代码,而不会再去编译第三方库,那么第三方库在第一次打包的时候只打包一次,以后只要我们不升级第三方包的时候,那么webpack就不会对这些库去打包,这样的可以快速的提高打包的速度。因此为了解决这个问题,DllPlugin 和 DllReferencePlugin插件就产生了。 https://www.webpackjs.com/plugins/dll-plugin/#dllplugin DLLPlugin 它能把第三方库代码分离开,并且每次文件更改的时候,它只会打包该项目自身的代码。所以打包速度会更快。 DLLPlugin 这个插件是在一个额外独立的webpack设置中创建一个只有dll的bundle,也就是说我们在项目根目录下除了有webpack.config.js,还会新建一个webpack.dll.config.js文件。webpack.dll.config.js作用是把所有的第三方库依赖打包到一个bundle的dll文件里面,还会生成一个名为 manifest.json文件。 DllReferencePlugin 这个插件是在webpack.config.js中使用的,该插件的作用是把刚刚在webpack.dll.config.js中打包生成的dll文件引用到需要的预编译的依赖上来。什么意思呢?就是说在webpack.dll.config.js中打包后比如会生成 vendor.dll.js文件和vendor-manifest.json文件,vendor.dll.js文件包含所有的第三方库文件,vendor-manifest.json文件会包含所有库代码的一个索引,当在使用webpack.config.js文件打包DllReferencePlugin插件的时候,会使用该DllReferencePlugin插件读取vendor-manifest.json文件,看看是否有该第三方库。vendor-manifest.json文件就是有一个第三方库的一个映射而已。 所以说 第一次使用 webpack.dll.config.js 文件会对第三方库打包,打包完成后就不会再打包它了,然后每次运行 webpack.config.js文件的时候,都会打包项目中本身的文件代码,当需要使用第三方依赖的时候,会使用 DllReferencePlugin插件去读取第三方依赖库。所以说它的打包速度会得到一个很大的提升。 DLLPlugin 和 DLLReferencePlugin 用某种方法实现了拆分 bundles,同时还大大提升了构建的速度。 var path = require("path"); var webpack = require("webpack"); var SRC_PATH = path.resolve(__dirname,‘./src‘); module.exports = { // 要打包的模块的数组 entry: { vendor: [‘vue/dist/vue.esm.js‘,‘vue-router‘] }, output: { path: path.join(__dirname, ‘./static/dll), // 打包后文件输出的位置 filename: ‘[name].dll.js‘,// vendor.dll.js中暴露出的全局变量名。 library: ‘[name]_library‘ // 与webpack.DllPlugin中的`name: ‘[name]_library‘,`保持一致。 }, plugins: [ new webpack.DllPlugin({ path: path.join(SRC_PATH,‘./static/dll/[name]-manifest.json‘), name: ‘[name]_library‘, context: __dirname }), ] }; DllPlugin 插件有三个配置项参数如下: 上面就是webpack.dll.conf.js的主要配置。执行之后会在static文件夹(在vue-cli生成的项目中用于存放不需要webpack构建的静态文件【@vue/cli中的目录名为Public】)下生成两个文件夹(lib文件夹和mainfest文件夹)。其中lib下的文件为我们已经打包好的组件库,mainfest下的文件在引入项目时有用(是一个JSON文件)。 在package.json的scripts里加上: "dll": "webpack --config webpack.dll.config.js", 运行npm run dll 在static下生成dll文件夹,dll文件夹里包括js文件和json文件 // 添加DllReferencePlugin插件 plugins: [ new webpack.DllReferencePlugin({ context: __dirname, manifest: require(‘./static/dll/vendor-manifest.json‘) }) ], DllReferencePlugin项的参数有如下: context: manifest文件中请求的上下文。 由于动态链接库我们一般只编译一次,除非依赖的三方库更新,之后就不用编译,因此入口的 index.js 文件中不包含这些模块,所以要在 index.html 中单独引入。 ① 第一种方式, 一种是根据打包的路径手动添加 ② 第二种方式,用add-asset-html-webpack-plugin或者html-webpack-include-assets-plugin插入到html中,简单自动化 下面着重讲下add-asset-html-webpack-plugin与html-webpack-include-assets-plugin插件的使用,项目中使用add-asset-html-webpack-plugin npm安装: npm install add-asset-html-webpack-plugin -D npm install html-webpack-include-assets-plugin -D Yarn安装: yarn add add-asset-html-webpack-plugin -D yarn add html-webpack-include-assets-plugin -D const AddAssetHtmlPlugin = require(‘add-asset-html-webpack-plugin‘); const HtmlWebpackIncludeAssetsPlugin = require(‘html-webpack-include-assets-plugin‘); module.exports = { ..., plugins: [ ..., // 给定的 JS 或 CSS 文件添加到 webpack 配置的文件中,并将其放入资源列表 html webpack插件注入到生成的 html 中。 new HtmlWebpackIncludeAssetsPlugin( { assets: [‘dll/asset.dll.js‘,‘dll/vendor.dll.js‘], append: false } ) ] 至此,配置之后的: 提示:由于HappyPack 对file-loader、url-loader 支持的不友好,所以不建议对该loader使用。 webpack打包哪一步最耗时?可能要数loader对文件的转换操作了,我们前面说过,我们使用loader将文件转换为我们需要的类型,文件数量巨大,webpack执行又是单线程的,转换的操作只能一个一个的处理,不能多件事一起做。 happypack 通过new HappyPack(),去实例化一个HappyPack对象,其实就是告诉Happypack核心调度器如何通过一系列loader去转换一类文件,并且可以指定如何为这类转换器作分配子进程。 参考:https://www.qdtalk.com/2018/11/16/webpack4plugin-2/ yarn add happypack --dev // 引入 happypack const HappyPack = require(‘happypack‘); // 创建 happypack 共享进程池,其中包含 6 个子进程 const happyThreadPool = HappyPack.ThreadPool({ size: 6 }); module.exports = { //省略部分配置 threadPool: happyThreadPool, 在 Loader 配置中,所有文件的处理都交给了 happypack/loader 去处理,使用紧跟其后的 querystring ?id=babel 去告诉 happypack/loader 去选择哪个 HappyPack 实例去处理文件。 在 Plugin 配置中,新增了两个 HappyPack 实例分别用于告诉 happypack/loader 去如何处理 .js 和 .css 文件。选项中的 id 属性的值和上面 querystring 中的 ?id=babel 相对应,选项中的 loaders 属性和 Loader 配置中一样。 对应的参数 id:String 用唯一的标识符 id 来代表当前的 HappyPack 是用来处理一类特定的文件. loaders: Array 用法和 webpack Loader 配置中一样. threads: Number 代表开启几个子进程去处理这一类型的文件,默认是3个,类型必须是整数。 verbose: Boolean 是否允许 HappyPack 输出日志,默认是 true。 threadPool: HappyThreadPool 代表共享进程池,即多个 HappyPack 实例都使用同一个共享进程池中的子进程去处理任务,以防止资源占用过多。 verboseWhenProfiling: Boolean 开启webpack --profile ,仍然希望HappyPack产生输出。 debug: Boolean 启用debug 用于故障排查。默认 false。 https://blog.csdn.net/zgd826237710/article/details/88172290#_HappyPack_36 注意 注意,webpack4中的happypack要使用5.0.0版本,如果你是从webpack3升级到webpack4,记得升级happypack 上面的loader中出现一个陌生词cacheDirectory: Webpack构建项目进一步优化 标签:html web 之间 代码 有用 更新 dirname get config 操作系统 原文地址:https://www.cnblogs.com/laneyfu/p/12269947.htmlStep14.Webpack构建项目进一步优化
webpack dll VS external
(1) dll与externals的区别
(2) externals
DLLPlugin 和 DLLReferencePlugin的使用
DLLPlugin
该manifest.json的作用是用来让 DllReferencePlugin 映射到相关的依赖上去的。(1) 配置webpack.dll.config.js:
context(可选): manifest文件中请求的上下文,默认为该webpack文件上下文。
name: 公开的dll函数的名称,和 output.library保持一致。
path: manifest.json 生成文件的位置和文件名称。(2) 在webpack.base.conf.js里加上:
manifest: 编译时的一个用于加载的JSON的manifest的绝对路径。
mainfest: 请求到模块id的映射(默认值为 manifest.content)
name: dll暴露的地方的名称(默认值为manifest.name)
scope: dll中内容的前缀。
sourceType: dll是如何暴露的libraryTarget。(3) 在index.html中引入vendor.dll.js:
安装大同小异
l add-asset-html-webpack-plugin的使用
module.exports = {
...,
plugins: [
...,
# 给定的 JS 或 CSS 文件添加到 webpack 配置的文件中,并将其放入资源列表 html webpack插件注入到生成的 html 中。
new AddAssetHtmlPlugin([
{
# 要添加到编译中的文件的绝对路径
filepath: path.resolve(__dirname,‘./static/dll/dll_vendor.js‘),
outputPath: ‘dll‘,
publicPath: ‘dll‘,
includeSourcemap: false
}
])
]
} l html-webpack-include-assets-plugin的使用
可以看到npm run build后的时间大幅度减少,在dist打包体积上也比之前的小。在项目优化中,可以很大程度上加快项目的构建速度和减少项目的打包体积。使用 happypack 提升 Webpack 项目构建速度
我们需要Webpack 能同一时间处理多个任务,发挥多核 CPU 电脑的威力,HappyPack 就能让 Webpack 做到这点,我们将需要通过loader处理的文件先交给happypack去处理,happypack 在收集到这些文件的处理权限后,统一分配CPU资源.happypack工作原理
核心调度器的逻辑代码在主进程里,也就是运行webpack的进程中,核心调度器会将一个个任务分配给当前空闲的子进程,子进程处理完后会将结果发送给核心调度器,它们之间的数据交换是通过进程间的通讯API实现的。
核心调度器收到来自子进程处理完毕的结果后,会通知webpack该文件已经处理完毕安装:
使用:
module: {
rules: [
{
test: /\.js$/,
//把对.js 的文件处理交给id为happyBabel 的HappyPack 的实例执行
use: ‘happypack/loader?id=happyBabel‘,
//排除node_modules 目录下的文件,合理的使用排除可以事半功倍
exclude: path.resolve(__dirname,‘node_modules‘)
},
]
},
plugins: [
new HappyPack({
//用id来标识 happypack处理那里类文件
id: ‘happyBabel‘,
//如何处理js文件 用法和loader 的配置一样
loaders: [{
loader: ‘babel-loader?cacheDirectory=true‘,
}],
//使用共享进程池中的自进程去处理任务
//允许 HappyPack 输出日志,默认为true
verbose: true,
})
]
}
cacheDirectory默认值为 false。
当有设置时,指定的目录将用来缓存 loader 的执行结果。之后的 webpack 构建,将会尝试读取缓存,来避免在每次执行时,可能产生的、高性能消耗的 Babel 重新编译过程(recompilation process)。如果设置了一个空值 (loader: ‘babel-loader?cacheDirectory’) 或者 true (loader: babel-loader?cacheDirectory=true),loader 将使用默认的缓存目录 node_modules/.cache/babel-loader,如果在任何根目录下都没有找到 node_modules 目录,将会降级回退到操作系统默认的临时文件目录。
上一篇:select用js设置选中的
下一篇:MVC5中Model设置属性注解