关于webpack4:webpack4和webpack5打包资源文件配置差异

我的项目中会有一些资源文件,比方图片资源,字体资源文件等。这些文件在打包的时候须要挪动到dist目录webpack4中,打包这些资源文件,须要用到url-loader和file-loader,file-loader把文件输入到一个文件夹中,在代码中通过绝对 URL 去援用输入的文件 (解决图片和字体)url-loader与 file-loader 相似,区别是用户能够设置一个阈值,大于阈值会交给 file-loader 解决,小于阈值时返回文件 base64 模式编码 (解决图片和字体) { test: /\.(png|svg|gif|jpe?g)$/, use: [ { loader: "url-loader", options: { name: "img/[name].[hash:8].[ext]", // outputPath:'img' limit: 1024 * 10, }, }, ], }webpack5中内置了解决资源文件的模块asset,不再须要file-loader和url-loader。 asset/resource -->file-loader( 输入门路 )asset/inline --->url-loader(所有 data uri)asset/source --->raw-loaderasset (parser )webpack5中如果用require加载图片,须要提取default属性能力拿到资源 Img.src = require("test.png").default;或者要在css-loader中配置esModule属性为false { test: /\.css$/, use: [ "style-loader", { loader: "css-loader", options: { importLoaders: 1, // 回退一步 esModule: false, }, }, "postcss-loader", ], },图片资源文件解决如下 ...

June 22, 2022 · 1 min · jiezi

关于webpack4:迷你版webpack实现

调试webpack过程理解执行流程 开始-合并配置------------实例化compile-------设置node文件读写能力-----通过循环挂载plugins-----解决webpack外部默认的插件(入口文件) 开始-compiler.beforeRun-compiler.run--------compiler.beforeCompile-compiler.compile-------compile.make 在Compiler类中,构造函数内会挂载大量的钩子,这些钩子都来自tapable,挂载之后在后续的操作中,这些钩子期待被触发执行。 this.hooks = { /** @type {SyncBailHook<Compilation>} */ shouldEmit: new SyncBailHook(["compilation"]), /** @type {AsyncSeriesHook<Stats>} */ done: new AsyncSeriesHook(["stats"]), /** @type {AsyncSeriesHook<>} */ additionalPass: new AsyncSeriesHook([]), /** @type {AsyncSeriesHook<Compiler>} */ beforeRun: new AsyncSeriesHook(["compiler"]), /** @type {AsyncSeriesHook<Compiler>} */ run: new AsyncSeriesHook(["compiler"]), /** @type {AsyncSeriesHook<Compilation>} */ emit: new AsyncSeriesHook(["compilation"]), /** @type {AsyncSeriesHook<string, Buffer>} */ assetEmitted: new AsyncSeriesHook(["file", "content"]), /** @type {AsyncSeriesHook<Compilation>} */ afterEmit: new AsyncSeriesHook(["compilation"]), /** @type {SyncHook<Compilation, CompilationParams>} */ thisCompilation: new SyncHook(["compilation", "params"]), /** @type {SyncHook<Compilation, CompilationParams>} */ compilation: new SyncHook(["compilation", "params"]), /** @type {SyncHook<NormalModuleFactory>} */ normalModuleFactory: new SyncHook(["normalModuleFactory"]), /** @type {SyncHook<ContextModuleFactory>} */ contextModuleFactory: new SyncHook(["contextModulefactory"]), /** @type {AsyncSeriesHook<CompilationParams>} */ beforeCompile: new AsyncSeriesHook(["params"]), /** @type {SyncHook<CompilationParams>} */ compile: new SyncHook(["params"]), /** @type {AsyncParallelHook<Compilation>} */ make: new AsyncParallelHook(["compilation"]), /** @type {AsyncSeriesHook<Compilation>} */ afterCompile: new AsyncSeriesHook(["compilation"]), /** @type {AsyncSeriesHook<Compiler>} */ watchRun: new AsyncSeriesHook(["compiler"]), /** @type {SyncHook<Error>} */ failed: new SyncHook(["error"]), /** @type {SyncHook<string, string>} */ invalid: new SyncHook(["filename", "changeTime"]), /** @type {SyncHook} */ watchClose: new SyncHook([]), /** @type {SyncBailHook<string, string, any[]>} */ infrastructureLog: new SyncBailHook(["origin", "type", "args"]), // TODO the following hooks are weirdly located here // TODO move them for webpack 5 /** @type {SyncHook} */ environment: new SyncHook([]), /** @type {SyncHook} */ afterEnvironment: new SyncHook([]), /** @type {SyncHook<Compiler>} */ afterPlugins: new SyncHook(["compiler"]), /** @type {SyncHook<Compiler>} */ afterResolvers: new SyncHook(["compiler"]), /** @type {SyncBailHook<string, Entry>} */ entryOption: new SyncBailHook(["context", "entry"]) };实现迷你版webpack临时不须要这么多钩子. ...

February 2, 2022 · 2 min · jiezi

关于webpack4:寻找webpack打包入口

node_modules下.bin目录下有一个webpack.cmd脚本文件,组装定位了要执行的webpack.js文件 "%~dp0\node.exe" "%~dp0\..\webpack\bin\webpack.js" %*将启动文件指向了webpack目录下的bin\webpack.js。 在webpack.js文件中,有一个runCommond办法和isInstalled判断包是否装置函数, const runCommand = (command, args) => { const cp = require("child_process"); return new Promise((resolve, reject) => { const executedCommand = cp.spawn(command, args, { stdio: "inherit", shell: true }); executedCommand.on("error", error => { reject(error); }); executedCommand.on("exit", code => { if (code === 0) { resolve(); } else { reject(); } }); });};const isInstalled = packageName => { try { require.resolve(packageName); return true; } catch (err) { return false; }};installedClis获取曾经装置的cli,这外面重要的就是CLIs数组中第一行isInstalled("webpack-cli"),指向了webpack-cli。 ...

February 1, 2022 · 1 min · jiezi

关于webpack4:webpack底层工具库tapable基本使用

tapable工作流程 实例化hook注册事件监听通过hook触发事件监听执行懒编译生成的可执行代码Hook本职是tapable实例对象,分同步和异步,异步分并行和串行两种模式 Hook执行特点Hook:一般钩子,监听器之间相互独立不烦扰BailHook:熔断钩子,某个监听返回非undefined时后续不执行WaterfallHoook: 瀑布钩子,上一个监听的返回值可传递至下一个LoopHook:循环钩子,如果以后未返回false则始终执行 tapable库同步钩子:SynckHook,SyncBailHoook,SyncWaterfallHook,SyncLoopHook异步串行钩子:AsyncSeriesHoook,AsyncSeriesBailHook,AsyncSeriesWaterfallHook,异步并行钩子:AsyncParallerHook,AsyncParalleBailHook 同步钩子:SyncHook let { SyncHook, SyncBailHook} = require('tapable')// 创立钩子let hook = new SyncHook(['name', 'age'])hook.tap('fn1', function (name, age) { console.log('fn1', name, age)})hook.tap('fn2', function (name, age) { console.log('fn2', name, age)})hook.tap('fn3', function (name, age) { console.log('fn3', name, age)})hook.call('jack', 18)后果都能因而打印 SyncBailHook let bailHook = new SyncBailHook(['name', 'age'])bailHook.tap('fn1', function (name, age) { console.log('fn1', name, age)})bailHook.tap('fn2', function (name, age) { console.log('fn2', name, age) return 'tom' // fn1,fn2,会打印,fn3不会打印 // return undefined // fn1,fn2,fn3都会打印})bailHook.tap('fn3', function (name, age) { console.log('fn3', name, age)})bailHook.call('jack', 18)如果返回非undefined,流程就会终止 ...

January 31, 2022 · 2 min · jiezi

关于webpack4:webpack单文件懒加载分析实现

log.js文件 module.exports ="lazy load logger"index.js文件 let oBtn = document.getElementById('btn')oBtn.addEventListener('click', function () { import( /*webpackChunkName: "log"*/ './log.js').then((log) => { console.log(log) })})console.log('index.js内容')点击按钮时,控制台显示lazy load loggerwebpack在打包后,比之前的单文件加载多出了几件事件。懒加载的实现次要通过Promise来实现。实现懒加载,要调用__webpack_require__.e办法,e办法是一个promise状态保留。e办法中,jsonP创立srcipt标签,指定src,通过Promise.all把状态往后传,在过程中,动静加载要被导入的内容,这里会通过window['webpackJsonP]调用push办法.调用webpackJsonpCallback办法,执行胜利的resolve办法,__webpack_require__.e后的then办法通过__webpack_require__.t办法加载log中的内容放在value中保留.这里多出的两个操作一个是jsonP,一个是__webpack_require__.e // 定义webpackJsonpCallback,合并模块定义,扭转promise状态,还有之后的then操作 function webpackJsonpCallback(data) { // 获取要被动静加载的模块id let chunkIds = data[0]; // 获取须要被动静加载模块的依赖关系对象 let moreModules = data[1] let chunkId let resolves = [] // 循环判断chunkIds里对应的模块内容是否曾经实现加载 for (let i = 0; i < chunkIds.length; i++) { chunkId = chunkIds[i] if (Object.prototype.hasOwnProperty.call(inStalledChunks, chunkId) && inStalledChunks[chunkId]) { //数组程序,resolve,reject,promise,这里是曾经加载,所以是0 resolves.push(inStalledChunks[chunkId][0]) } // 更新chunk状态 inStalledChunks[chunkId] = 0; } for (let moduleId in moreModules) { if (Object.prototype.hasOwnProperty.call(moreModules, moduleId)) { modules[moduleId] = moreModules[moduleId] } } while (resolves.length) { resolves.shift()() } } // 定义inStalledChunks 用于标识某个chunkId对应的chunk是否实现加载 let inStalledChunks = { main: 0 } // 定义jsonpScriptSrc实现src的解决 function jsonpScriptSrc(chunkId) { return __webpack_require__.p + "" + chunkId + '.built.js' } // 定义e办法,用于实现 :实现jsonP异步加载,利用promise来实现异步加载操作 __webpack_require__.e = function (chunkId) { // 定义一个数组用于寄存promise let promises = []; // 获取chunkId对应的chunk是否曾经实现了加载 let installedChunkData = inStalledChunks[chunkId] // 根据以后是否已实现加载的状态来执行后续的逻辑 if (installedChunkData !== 0) { if (installedChunkData) { // push一个残缺的promise promises.push(installedChunkData[2]) } else { // 执行加载操作 let promise = new Promise((resolve, reject) => { installedChunkData = inStalledChunks[chunkId] = [resolve, reject] }) promises.push(installedChunkData[2] = promise) // 创立标签 let script = document.createElement('script') // 设置src script.src = jsonpScriptSrc(chunkId) // 写入script标签 document.head.appendChild(script) } } // 执行promise return Promise.all(promises) }

January 31, 2022 · 1 min · jiezi

关于webpack4:根据webpack打包规则实现简单的打包手写实现

首先导入导出分为几类 CommonJS导入CommonJSEsModule导入CommonJSEsModule导入EsModule依据实现规定,简略代码样例 // index.js// import log,{age} from "./log.js"// // let log = require('./log.js')// console.log('index.js内容')// console.log("log", log,age)// log.js// CommonJS导出module.exports ="logger"// export default "jack"// export const age = 18;手写模仿实现代码 (function (modules) { // 缓存被加载过的模块 let installedModules = {}; // 定义一个__webpak_require__办法来替换 import require的加载操作 function __webpack_require__(moduleId) { // 缓存优先,判断以后缓存中是否存在要被加载的模块,如果存在就间接返回 if (installedModules[moduleId]) { return installedModules[moduleId].exports } // 如果以后缓存中不存在,就须要本人定义,执行被导入的模块内容加载 let module = installedModules[moduleId] = { i: moduleId, l: false, exports: {} } // 调用以后moduleId对应的函数,实现内容的加载,__webpack_require__c参数存在是为了解决递归调用的问题 modules[moduleId].call(module.exports, module, module.exports, __webpack_require__) // 当上述办法调用完结之后,批改 l 的值,标识以后模块内容曾经加载实现了 module.l = true // 加载工作实现之后,将拿回来的内容返回至调用地位 return module.exports } // 定义m属性来保留modules __webpack_require__.m = modules // 定义c属性用于保留cache __webpack_require__.c = installedModules // 定义o办法用于判断对象身上是否存在制订属性 __webpack_require__.o = function (object, property) { return Object.prototype.hasOwnProperty(object, property) } // 定义d办法用于在对象身上增加制订属性,并且给该属性提供一个getter __webpack_require__.d = function (exports, name, getter) { if (!__webpack_require__.o(exports, name)) { Object.defineProperty(exports, name, { enumerable: true, get: getter }); } } // 定义r办法用于标识以后模块EsModule __webpack_require__.r = function (exports) { if (typeof Symbol !== undefined && Symbol.toStringTag) { Object.defineProperty(exports, Symbol.toStringTag, { value: "module" }) } Object.defineProperty(exports, "__esModule", { value: true }) } // 定义n办法用于设置具体的getter __webpack_require__.n = function (module) { let getter = module && module.__esModule ? function getDefault() { return module['default'] } : function getModuleExports() { return module } __webpack_require__.d(getter, 'a', getter) return getter } // 定义p属性,用于保留资源拜访门路 __webpack_require__.p = "" // 调用__webpack_require__办法,执行模块导入和加载操作 return __webpack_require__(__webpack_require__.s = "./src/index.js")})( // CommonJS导入CommonJS // { // "./src/index.js": (function (module, exports, __webpack_require__) { // let log = __webpack_require__( /*! ./log.js */ "./src/log.js") // console.log('index.js内容') // console.log("log", log) // }), // "./src/log.js": (function (module, exports) { // // CommonJS导出 // module.exports = "logger" // }) // } // EsModule导入CommonJS { "./src/index.js": (function (module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); var _log_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__( /*! ./log.js */ "./src/log.js"); var _log_js__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/ __webpack_require__.n(_log_js__WEBPACK_IMPORTED_MODULE_0__); console.log('index.js内容') console.log("log", _log_js__WEBPACK_IMPORTED_MODULE_0___default.a) }), "./src/log.js": (function (module, exports) { module.exports = "logger" }) } // EsModule导入EsModule // { // "./src/index.js": (function (module, __webpack_exports__, __webpack_require__) { // "use strict"; // __webpack_require__.r(__webpack_exports__); // var _log_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__( /*! ./log.js */ "./src/log.js"); // console.log('index.js内容') // console.log("log", _log_js__WEBPACK_IMPORTED_MODULE_0__["default"], _log_js__WEBPACK_IMPORTED_MODULE_0__["age"]) // }), // "./src/log.js": (function (module, __webpack_exports__, __webpack_require__) { // "use strict"; // __webpack_require__.r(__webpack_exports__); // __webpack_require__.d(__webpack_exports__, "age", function () { // return age; // }); // __webpack_exports__["default"] = ("jack"); // const age = 18; // }) // })通过编译生成的index.html,引入手写built.js文件,控制台能够失常打印 ...

January 30, 2022 · 2 min · jiezi

关于webpack4:CommonJS规范下webpack单文件打包

依赖版本 "webpack": "^4.44.2","webpack-cli": "^3.3.12"一个简略的文件通过webpack打包 // 导出console.log('index.js')module.exports = '导出内容'// 导入let log = require('./log.js')console.log('index.js内容')console.log(log)打包后文件 (function (modules) { // webpackBootstrap // The module cache var installedModules = {}; // 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 // 把index.js导出内容挂载到exports上 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; } // expose the modules object (__webpack_modules__) __webpack_require__.m = modules; // expose the module cache __webpack_require__.c = installedModules; // define getter function for harmony exports __webpack_require__.d = function (exports, name, getter) { if (!__webpack_require__.o(exports, name)) { Object.defineProperty(exports, name, { enumerable: true, get: getter }); } }; // define __esModule on exports __webpack_require__.r = function (exports) { if (typeof Symbol !== 'undefined' && Symbol.toStringTag) { Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' }); } Object.defineProperty(exports, '__esModule', { value: true }); }; // create a fake namespace object // mode & 1: value is a module id, require it // mode & 2: merge all properties of value into the ns // mode & 4: return value when already ns object // mode & 8|1: behave like require __webpack_require__.t = function (value, mode) { if (mode & 1) value = __webpack_require__(value); if (mode & 8) return value; if ((mode & 4) && typeof value === 'object' && value && value.__esModule) return value; var ns = Object.create(null); __webpack_require__.r(ns); Object.defineProperty(ns, 'default', { enumerable: true, value: value }); if (mode & 2 && typeof value != 'string') for (var key in value) __webpack_require__.d(ns, key, function (key) { return value[key]; }.bind(null, key)); return ns; }; // getDefaultExport function for compatibility with non-harmony modules __webpack_require__.n = function (module) { var getter = module && module.__esModule ? function getDefault() { return module['default']; } : function getModuleExports() { return module; }; __webpack_require__.d(getter, 'a', getter); return getter; }; // Object.prototype.hasOwnProperty.call __webpack_require__.o = function (object, property) { return Object.prototype.hasOwnProperty.call(object, property); }; // __webpack_public_path__ __webpack_require__.p = ""; // Load entry module and return exports return __webpack_require__(__webpack_require__.s = "./src/index.js"); }) ({ "./src/index.js": /*! no static exports found */ (function (module, exports) { console.log('index.js内容') module.exports = '入口文件导出内容' }) });打包文件剖析特点剖析 ...

January 30, 2022 · 3 min · jiezi

关于webpack4:webpack4从0搭建组件库

代码拆散代码拆散办法有三种: 入口终点:应用 entry 配置手动地拆散代码。避免反复:应用 SplitChunksPlugin 去重和拆散 chunk。动静导入:通过模块中的内联函数调用来拆散代码。动静导入(dynamic imports)import()require.ensure预取/预加载模块(prefetch/preload module)webpack v4.6.0+ 增加了预取和预加载的反对。 在申明 import 时,应用上面这些内置指令,能够让 webpack 输入 "resource hint(资源提醒)",来告知浏览器: prefetch(预取):未来某些导航下可能须要的资源preload(预加载):以后导航下可能须要资源配置项重点详解(1)mode: "pruduction"启用 minification(代码压缩) 和 tree shaking (usedExports:true)主动指定DefinePlugin:process.env.NODE_ENV === 'production'(2)devtoolsource map 简介 生产环境:source-map开发环境:inline-source-map(3)optimizationsplitChunkssplitChunks: { chunks: 'all', // 提取公共模块 loadash // 将第三方库(library)(例如 lodash 或 react)提取到独自的 vendor chunk 文件中,是比拟举荐的做法 // 利用 client 的长效缓存机制,命中缓存来打消申请,并缩小向 server 获取资源,同时还能保障 client 代码和 server 代码版本统一。 cacheGroups: { vendor: { test: /[\\/]node_modules[\\/]/, name: 'vendors', chunks: 'all' } }},runtimeChunkruntimeChunk: 'single' // 提取疏导模板 将 runtime 代码拆分为一个独自的 chunk(5)output// filename: '[name].[contenthash].js', // content hash 内容变动才会变动filename: 'webpack-numbers.js', path: path.resolve(__dirname, 'dist'),// 裸露 library 这是库名称 import from 'webpackNumbers'library: 'webpackNumbers', libraryTarget: 'umd'(6)pluginsHashedModuleIdsPluginconst { HashedModuleIdsPlugin } = require('webpack');plugins: [ // 不会因模块减少和缩小导致的模块内容变动,减少长缓存命中机制 new HashedModuleIdsPlugin()],BundleAnalyzerPlugin剖析打包代码 ...

November 28, 2020 · 1 min · jiezi

关于webpack4:webpack之开发环境development

一,loader加载器1,image-webpack-loader(1)目标:对图片image和svg等文件进行压缩,(2)流程:通过image-webpack-loader,打包后就会压缩,文件体积就会少上很多。vue-cli3.x的配置如下:`config.module.rule('images')//开启图片压缩.test(/.(png|jpe?g|gif)(?.*)?$/).use('image-webpack-loader').loader('image-webpack-loader').options({ bypassOnDebug: true })config.module.rule('svg')//开启svg压缩.test(/.(svg)(?.*)?$/).use('image-webpack-loader').loader('image-webpack-loader').options({ bypassOnDebug: true })`*应用过程留神点:须用cnpm装置(因为该插件注册表在cnpm,·https://developer.aliyun.com/mirror/npm/package/image-webpack-loader),如果用过yarn和npm装置过,记得卸载,而后再用cnpm装置;

September 25, 2020 · 1 min · jiezi

关于webpack4:webpack4-babel7-配置ie兼容

有一说一, IE真是让人头大????♂️????♂️以下只给出如何配置, 如果想理解更多请查看文末传送门 装置:npm i @babel/polyfill -Snpm i @babel/preset-env @babel/plugin-transform-runtime -D// 依据babel.config.json中corejs 2 / 3, 自行抉择装置 @babel/runtime-corejs2 或 @babel/runtime-corejs3npm i @babel/runtime-corejs3 -Dwebpack.config.js entry: { main: ['@babel/polyfill', './main.js'] }babel.config.json"presets": ["@babel/preset-env"],"plugins": [ [ "@babel/plugin-transform-runtime", { "corejs": 3 } ] ]----------------------- 顺便说一下 ------------------------ 开发环境下, 在ie上可能一片空白, 有以下三种计划 build后在ie上调试 [ 可行, 但太麻烦了 ]devServer inline设置成false [ 可行, 然而iframe模式下, HRM会生效, 须要手动刷新页面 ]升高devServer版本到@2.11.1 [ 没试过 ]再说一遍, IE真真真是让人头大 ???????????? 相干材料转送:@babel/polyfill@babel/plugin-transform-runtimepreset-env与plugin-transform-runtime 应用及场景区别

September 17, 2020 · 1 min · jiezi

关于webpack4:webpack-插件开发webpackperloadparallelplugin

开发起因:因为我的项目是vue的页面级组件有差不多100个,举个case:因为用了 webpack-preftech-pulgin 插件, 页面里会插入 100个 <link href="xxx" as="script" rel="preftech">标签.通过在chrome 外面调试发现 当页面里有过多preftech 会阻塞主文件的下载速度,也就是会抢占重要资源的下载速度。所以我采纳另一种实现形式,限度最大同时预下载(未来须要)的 资源的数量,缩小因为资源下载过多,造成首页渲染过慢。包地址插件主代码 // 插件地址const fs = require('fs')const path = require('path');const Entrypoint = require('webpack/lib/Entrypoint.js');const assert = require('assert');class HtmlWebpackPreFetch { constructor(options = { paralleMax: 3 }) { this.options = options } apply(complier) { complier.hooks.compilation.tap(this.constructor.name, compilation => { // hook HtmlWebpackPlugin 输入 index.html之前的钩子,为了革新输入 index.html 文件内容(来自某个webpack 插件) let hook = compilation.hooks.htmlWebpackPluginAfterHtmlProcessing; if (!hook) { const [HtmlWebpackPlugin] = complier.options.plugins.filter( (plugin) => plugin.constructor.name === 'HtmlWebpackPlugin'); assert(HtmlWebpackPlugin, 'Unable to find an instance of ' + 'HtmlWebpackPlugin in the current compilation.'); hook = HtmlWebpackPlugin.constructor.getHooks(compilation).beforeEmit; } // 对对应的钩子 注册事件,我是这个认为???? hook.tapAsync( this.constructor.name, (htmlPluginData, callback) => { try { const { outputOptions: { publicPath = '' } , chunks, chunkGroups} = compilation; // split chunks 找到非入口文件 const sourceList = chunkGroups.filter(chunkGroup => { return !(chunkGroup instanceof Entrypoint) && !chunkGroup.isInitial() }).map(chunkGroup => chunkGroup.chunks.reduce((p, q) => { return { files: [...p.files, q.files] } , {files: []} })).reduce((p, n) => { return { files: [...p.files, ...n.files] } } , {files: []}).files.map(path => (`${publicPath}${path}`)) // loadTemplate.js 实现并发加载模版文件 let loadJsTemplate = fs.readFileSync(path.join(__dirname, './loadTemplate.js'), { encoding: 'utf-8' }) // 获取要下载的文件 和 配置参数 const templateOptions = JSON.stringify({ sourceList, ...this.options }) loadJsTemplate = loadJsTemplate.replace('/*injectOptions*/', templateOptions) let htmlTemplate = htmlPluginData.html const htmlTemplateList = htmlTemplate.split('</body>') htmlTemplateList.splice(1, 0, `<script>${loadJsTemplate}</script></body>`) htmlTemplate = htmlTemplateList.join(''); htmlPluginData.html = htmlTemplate callback(null, htmlPluginData); } catch (error) { callback(error); } } ); })}}module.exports = HtmlWebpackPreFetch并行下载文件 loadTemplate.js ...

August 28, 2020 · 3 min · jiezi

关于webpack4:webpack概念

一,模式mode1,开发模式,development包管理工具的--dev指令,是指包装置在改位子。2,生产模式,production 二,出入口入口:所有资源的被打包的入口文件进口:管制所有入口文件打包后的位子 三,loader四,Plugin1,compression-webpack-plugin事后筹备的资源压缩版本,应用 Content-Encoding 提供拜访服务⑴流程,①将文件通过算法压缩,搁置在动态服务器(nginx)上,在浏览器上输出地址后发送申请,响应头设置gzip,告知浏览器承受一个gzip资源。

August 23, 2020 · 1 min · jiezi

webpack学习笔记CodeSplitting

我的环境win 10node v10.13.0npm 6.13.4webpack 4.43.0webpack-cli 3.3.12webpack-dev-server 3.11.0webpack-merge 5.0.7引言在开发中,我们开发单页应用时,代码越来越多,还引入了很多第三方库,打包后的代码就会很大。每次要下载很久,用户访问时下载也很慢,重新访问页面时,又要加载这么大的文件。如果我们能把代码拆分开,业务逻辑代码和第三方库的代码分离,那业务改变时,只会重新加载业务逻辑代码,第三方的代码被缓存下来。如果没有webpack,我们就要手动去实现这样的功能,但是有webpack就变得很容易了。 操作首先会手动去实现代码分离,然后再利用webpack的配置,去实现相对应的效果。 1.手动实现1.1以lodash做实验,我们先安装,它是一个模块化的工具库,可以简化array、number、objects、string 的使用npm i lodash -D 1.2然后去在src目录创建一个ventor.js,书写以下内容 import _ from 'lodash'window._ = _;在src目录创建index.js书写以下内容 console.log(_.join(["1","2","3"]),"fff");console.log(_.join(["1","2","3"]),"ttt");1.3webpack的entry配置如下即可 entry:{ ventor:'./src/ventor.js', bundle:'./src/index.js', },2.通过webpack配置实现2.1index.js文件如下,删掉ventor.js import _ from 'lodash'console.log(_.join(["1","2","3"]),"fff");console.log(_.join(["1","2","3"]),"ttt");2.2entry的配置也要改一下 entry:{ // ventor:'./src/ventor.js', bundle:'./src/index.js', },2.3每次都手动实现太繁琐了,webpack可以通过配置或者plugin去实现,这里加入了optimization配置项去实现。 optimization:{ //加入CodeSpliting splitChunks:{ chunks:'all' } }, output:{ // publicPath:"./", filename: '[name].js', path: path.resolve(__dirname,'dist') },2.4运行打包命令 npm run bundle可以看见dist目录下,webpack帮我们自动拆分了代码 3.异步importwebpack4如果我们不使用同步import,也可以使用异步import(要记得配置一下babel,默认不支持这种试验性语法),使用异步import的话,webpack会自动CodeSpliting 总结这里学会了使用webpack去拆分代码,提高js的打包和加载性能。

July 7, 2020 · 1 min · jiezi

webpack4X修改SplitChunksPluginvendorsfilename报错

报错内容:You are trying to set a filename for a chunk which is (also) loaded on demand. The runtime can only handle loading of chunks which match the chunkFilename schema. Using a custom filename would fail at runtime. (cache group: defaultVendors)module.exports = { // 此处省略其他配置项 ... optimization: { splitChunks: { chunks: 'all', minSize: 30000, //minRemainingSize: 0, maxSize: 0, minChunks: 1, maxAsyncRequests: 6, maxInitialRequests: 4, automaticNameDelimiter: '~', // 下面两个属性如果设置成两个false,打包后就不会出现verndors~前缀 // cacheGroups: { // vendors: false, // default: false // } cacheGroups: { defaultVendors: { test: /[\\/]node_modules[\\/]/, priority: -10 //filename: 'vendors' }, default: { //minChunks: 2, priority: -20, reuseExistingChunk: true //filename: 'common' } } } } ...}解决办法:注释掉filename原因在文档中有: 缓存组设置filename时,在chunks项配置为inital时才会生效,我们分割同步代码时,可以设置chunk为inital,这样就可以自定义filename了。否则会报错。 ...

June 29, 2020 · 1 min · jiezi

webpack4当webpack配置文件不在根目录时如何配置CleanWebpackPlugin

新版clean-webpack-plugin在使用上一共两个变化。1.不需要指定打包文件名,他会自动找output下面的配置。2.引入时需要使用一个对象去接收目录展示 版本展示// package.json"webpack": "^4.43.0","webpack-cli": "^3.3.11","clean-webpack-plugin": "^3.0.0",导入const { CleanWebpackPlugin} = require('clean-webpack-plugin');配置// webpack.config.jsplugins: [ new webpack.ProgressPlugin(), new CleanWebpackPlugin(), new HtmlWebpackPlugin({ template: 'index.html' })],output: { filename: 'bundle.js', path: path.resolve(__dirname, '../dist')}

June 28, 2020 · 1 min · jiezi

vue单文件组件无法获取refs的问题

原文https://blog.phyer.cn/article...记录一下学习webpack+vue碰到的一个大坑,踩这个坑是我才疏学浅的表现,特此引以为戒。因为该坑实在是太坑了! 代码header.html <body> <div id="popup-wrap"> <popup ref="popup"></popup> </div></body>header.js import popup from '../../components/popup/popup.vue'import './header.scss'let header_vue;$(function () { header_vue = new Vue({ el: '#popup-wrap', data: { }, mounted: { // 输出为{popup: VueComponent} console.log(this.$refs); } components: {popup}, methods: { pop_data: function () { // 输出为{} console.log(this.$refs); } } });});export {header_vue}other.js import {header_vue} from "../header/header";$(function () { header_vue.pop_data()});popup.vue是一个普通的弹窗组件。我在header.js中引入该组件,并实例化一个header_vue使用了popup组件,然后在other.js中引入header_vue试图使用pop_data函数,该函数仅输出header_vue的$refs,经测试,该函数输出为一个空的对象,但是mounted钩子正常输出。我就很纳闷,为啥mounted输出正常,函数调用就成空的了呢,Vue也已经挂载完成了啊。 resolve一番气急败坏的debug后,在header.js的$(function())加上了一句console.log('ok'),结果浏览器输出了俩ok。短时间大脑的高速运转后,我发现了问题的所在: webpack打包了两遍header.js!所以解决的办法就是把header_vue = new Vue()改成window.header_vue = new Vue()。别处直接用就行了。 尾话目前没搞清楚具体的bug出现原因,正常使用webpack多次引入同一个export也没有出现过此问题。但是肯定是我没学明白,有大牛知道的话麻烦解答解答。

June 24, 2020 · 1 min · jiezi