webpack浅析

mac2022-06-30  20

1.介绍webpack

webpack是模块打包机,宗旨是一切皆模块。通过入口文件解析打包成bundle.js文件,通过loader转换不能识别的less,sass,图片,.vue等文件,通过plugin扩展webpack功能。

module:编写源代码,export导出的模块,

bundle:打包出来的文件

chunk:bundle分解出来的,通常和bundle是一对一的关系,但也不总是。输出的时候可以更改chunkfilename,每一个chunk有它的chunkid.一个chunk,也可以包括多个module

2.升级webpack4

安装npm-check-updates文件,更新pakage.json文件

删除node_modules文件和pakage-lock.json文件

重新安装webpack-cli(因为webpack4中webpack-cli和webpack分成两个npm包

babel-core报错,安装回babel-loader7.1.5

extract-css-plugin更新到@next版本(或者使用mini-css-extract-plugin推荐使用,两者区别,前者会把所有css文件打包到一个app.css文件,后者会依据懒加载方式拆分,这样页面css可以和js一样使用按需加载)

mini-css-extract-plugin使用注意修改:

//util.js更改

 

if (options.extract) { // return ExtractTextPlugin.extract({ // use: loaders, // fallback: 'vue-style-loader' // }) if(process.env.NODE_ENV !== 'production'){ return ['style-loader'].concat(loaders) } return [miniCssExtractPlugin.loader].concat(loaders) } else { return ['vue-style-loader'].concat(loaders) }

//webpack.prod.js修改

// new ExtractTextPlugin({ // filename: utils.assetsPath('css/[name].[hash].css'), // allChunks: true, // }), new miniCssExtractPlugin({ filename: utils.assetsPath('css/[name].[chunkhash].css'), allChunks: true, }),

去掉commonChunk配置,增加optimization.splitChunks,和plugins通层级

optimization: { splitChunks: { chunks: "all", minSize: 30000, minChunks: 1, maxAsyncRequests: 5, maxInitialRequests: 3, automaticNameDelimiter: '~', name: true, cacheGroups: { async: { chunks: "async", minChunks: 1, // 代码块至少被引用的次数 maxInitialRequests: 3, // 设置最大的请求数 minSize: 0, // 设置每个 chunk 最小的大小 (默认30000),这里设置为 0,以方便测试 automaticNameDelimiter: '~', priority: 8 }, vendors: { chunks: "all", // 使用 all 模式 test: /[\\/]node_modules[\\/]/, // 匹配 node_modules 下的模块 name: "vendors", // 包命名,最终的命名要结合 output 的 chunkFilename minChunks: 1, minSize: 30000, priority: 10, // 设置优先级 reuseExistingChunk: true, }, common: { chunks: "all", minChunks: 2, name:'common', priority: 9, reuseExistingChunk: true } } }, runtimeChunk: { name: 'manifest' } }

添加mode

添加vue-loader里面的vueLoaderPlugin

//webpack.base.js

const { VueLoaderPlugin } = require('vue-loader')

plugins: [ new VueLoaderPlugin() ],

 

3.项目优化

缓存、懒加载、压缩代码、内嵌图片、内嵌manifest、合并碎片包(js打包输出文件不适合太多,因为浏览器加载js线程一般为4到5个,所以文件比较小的一些第三方或公共js不适合单独打包成一个文件)

使用external cdn

 

<script src="https://cdn.staticfile.org/vue/2.6.10/vue.min.js" type="text/javascript"></script> <!-- 为cdn引入资源不会阻塞页面渲染可以在script上添加defer或者async,异步加载 --> <!-- async异步加载完成后,会立即执行,执行时间会阻塞html parse,所以不适合用来有dom操作的js文件 --> <!-- defer异步加载完成后,会在html parse之后执行--> <!-- vue 使用cdn加载不适合defer和async-->

 

4.打包文件分析(webpack4)

打包后的manifest.js文件是一个立即执行函数、可以对照打包后的boostrap.js查看

//webpackJsonp.push之后的回调执行函数

function webpackJsonpCallback(data) { 

...//省略

return checkDeferredModules(); };

//加载函数

// The require function function __webpack_require__(moduleId) {

// Check if module is in cache if(installedModules[moduleId]) { return installedModules[moduleId].exports; } // Create a new module (and put it into the cache) var module = installedModules[moduleId] = { i: moduleId, l: false, exports: {} };

// Execute the module function modules[moduleId].call(module.exports, module, module.exports, __webpack_require__);

// Flag the module as loaded module.l = true;

// Return the exports of the module return module.exports; }

// The chunk loading function for additional chunks __webpack_require__.e = function requireEnsure(chunkId) { var promises = [];

// mini-css-extract-plugin CSS loading var cssChunks = {"3":1,"4":1}; if(installedCssChunks[chunkId]) promises.push(installedCssChunks[chunkId]); else if(installedCssChunks[chunkId] !== 0 && cssChunks[chunkId]) { promises.push(installedCssChunks[chunkId] = new Promise(function(resolve, reject) {...//省略 };

// JSONP chunk loading for javascript

var installedChunkData = installedChunks[chunkId]; if(installedChunkData !== 0) { // 0 means "already installed".

// a Promise means "currently loading". if(installedChunkData) { promises.push(installedChunkData[2]); } else { // setup Promise in chunk cache var promise = new Promise(function(resolve, reject) { installedChunkData = installedChunks[chunkId] = [resolve, reject]; }); promises.push(installedChunkData[2] = promise);

...//省略

return Promise.all(promises); };

var jsonpArray = window["webpackJsonp"] = window["webpackJsonp"] || []; var oldJsonpFunction = jsonpArray.push.bind(jsonpArray); jsonpArray.push = webpackJsonpCallback;(这里重置push函数,当别的文件使用window['webpackJsonp'].push的时候会调用这个函数) jsonpArray = jsonpArray.slice(); for(var i = 0; i < jsonpArray.length; i++) webpackJsonpCallback(jsonpArray[i]); var parentJsonpFunction = oldJsonpFunction;

参考文件webpack是怎么运行的

5.构建流程

Webpack 就像一条生产线,要经过一系列处理流程后才能将源文件转换成输出结果。 这条生产线上的每个处理流程的职责都是单一的,多个流程之间有存在依赖关系,只有完成当前处理后才能交给下一个流程去处理。 插件就像是一个插入到生产线中的一个功能,在特定的时机对生产线上的资源做处理。 Webpack 通过 Tapable 来组织这条复杂的生产线。 Webpack 在运行过程中会广播事件,插件只需要监听它所关心的事件,就能加入到这条生产线中,去改变生产线的运作。 Webpack 的事件流机制保证了插件的有序性,使得整个系统扩展性很好。 —吴浩麟《深入浅出webpack》

解析webpack配置参数,合并从shell传入和webpack.config.js文件里配置的参数,生产最后的配置结果。注册所有配置的插件,好让插件监听webpack构建生命周期的事件节点,以做出对应的反应。从配置的entry入口文件开始解析文件构建AST语法树,找出每个文件所依赖的文件,递归下去。在解析文件递归的过程中根据文件类型和loader配置找出合适的loader用来对文件进行转换。递归完后得到每个文件的最终结果,根据entry配置生成代码块chunk。输出所有chunk到文件系统。

初始化配置参数 -> 绑定事件钩子回调(这里相当于一个订阅和发布) -> 确定Entry逐一遍历 -> 使用loader编译文件 -> 输出文件

 

6.webpack插件介绍

参考webpack插件

转载于:https://www.cnblogs.com/sisi2020/p/11369456.html

相关资源:JAVA上百实例源码以及开源项目
最新回复(0)