关于webpack:webpackpublicPath

了解webpack中各种publicPath的含意output中的publicPathtype: function | string对于按需加载(on-demand-load)或加载内部资源(external resources)(如图片、文件等)来说,output.publicPath 是很重要的选项。如果指定了一个谬误的值,则在加载这些资源时会收到 404 谬误。 htmlWebpackPlugin的publicPatchtype: stringdefault: 'auto'用户<script>和<link>的publicPath devServer的publicPath其实,咱们常常容易搞混的就是output的publicPath和deveServer的publicPatch。 在开发阶段,咱们借用 devServer 启动一个开发服务器进行开发,这里也会配置一个 publicPath,这里的 publicPath 门路下的打包文件能够在浏览器中拜访。而动态资源依然应用 output.publicPath。 webpack-dev-server 打包的内容是放在内存中的,这些打包后的资源对外的的根目录就是 publicPath,换句话说,动态资源在内存中的门路都是以 publicPath 为准的。 确保 devServer.publicPath 始终以正斜杠结尾和结尾 从文档中,咱们能够看到 倡议 devServer.publicPath 与 output.publicPath 雷同,这是为啥?因为平时咱们我的项目生成 html 文件都是应用 webpack 插件 html-webpack-plugin 生成,其中波及到 js、css、img 的动态文件的门路解决,html-webpack-plugin 是基于 output.publicPath 生成最终拜访链接的。 如果 webpack-dev-server 的 publicPath 和 output.publicPath 不统一,在应用 html-webpack-plugin 可能会导致援用动态资源失败,因为在 webpack-dev-server 中生成 html 时,html-webpack-plugin 依然以 output.publicPath 援用动态资源,和 webpack-dev-server 的提供的资源拜访门路不统一,从而无奈失常拜访。 vue-cli的publicPathType: stringDefault: '/'用法和 webpack 自身的 output.publicPath 统一,然而 Vue CLI 在一些其余中央也须要用到这个值,所以请始终应用 publicPath 而不要间接批改 webpack 的 output.publicPath。这个值也能够被设置为空字符串 ('') 或是相对路径 ('./'),这样所有的资源都会被链接为相对路径,这样打进去的包能够被部署在任意门路,也能够用在相似 Cordova hybrid 利用的文件系统中。 ...

March 25, 2022 · 1 min · jiezi

关于webpack:爪哇学习笔记Webpack原理

前端工程化技术选型对立标准——eslint、husky测试、部署、监控——ut、e2e、mock性能优化模块化重构webpack流程webpack的构建流程能够分为以下三大阶段: 初始化:启动构建,读取与合并配置参数,加载Plugin,实例化Compiler。编译:从Entry登程,针对每个Module串行调用对应Loader去翻译文件的内容,再找到该Module依赖的Module,递归地进行编译解决。输入:将编译后的Module组合成Chunk,将Chunk转换成文件,输入到文件系统中。LoaderLoader就像一个翻译员,能将源文件通过转化后输入新的后果,并且一个文件还能够链式地通过多个翻译员翻译。在开发一个Loader时,请确保其职责的单一性,咱们只须要关怀输出和输入。 根底Webpack是运行在Node.js上的,一个Loader其实就是一个Node.js模块,这个模块须要导出一个函数。这个导出的函数的工作就是取得解决前的原内容,对原内容执行解决后,返回解决后的内容。 一个最简的的Loader的源码如下: // source为compiler传递给Loader的一个文件的原内容module.exports = function(source) { // TODO: 对文件内容进行解决 return source;}因为Loader运行在Node.js中,所以咱们能够调用任意Node.js自带的API,或者装置第三方模块进行调用: const sass = require('node-sass');module.exports = function(source) { return sass(source);}进阶取得Loader的optionsconst loaderUtils = require('loader-utils'); // getOptions办法要求loader-utils版本为2.xmodule.exports = function(source) { // 获取用户为以后Loader传入的options const options = loaderUtils.getOptions(this); return source;}返回其余后果下面的Loader都只是返回了原内容转换后的内容,然而在某些场景下还须要返回除了内容之外的货色。 以用babel-loader转换ES6为例,它还须要输入转换后的ES5代码对应的Source Map,以不便调试源码。 module.exports = function(source) { this.callback(null, source, sourceMaps); return;}其中的this.callback是Webpack向Loader注入的API(The Loader Context),以不便Loader和Webpack之间通信。 this.callback能够同步或者异步调用的并返回多个后果的函数。预期的参数是: this.callback( err: Error | null, content: string | Buffer, sourceMap?: SourceMap, meta?: any);如果这个函数被调用的话,你应该返回 undefined 从而防止含混的 loader 后果。 ...

March 15, 2022 · 2 min · jiezi

关于webpack:编写webpack插件删除没有被依赖的业务文件

背景SCRM 我的项目须要交接给另外一个部门。领导出于一些思考,须要把对方只须要的性能保留,其余性能删除,而后把代码上传到新的仓库地址,再作交接。 和产品经理沟通之后,明确了以下需要: 以页面(性能)为单位,保留或者删除个别页面须要删除一些性能问题剖析以页面(性能)为单位,保留或者删除。也就是说,依照粒度从大到细,一个路由对应着一个页面,一个页面可能蕴含多个tab,一个页面有多个资源(导入进来的组件、api文件、图片、utils办法等等),而它们也分全局和部分的。 粒度越大,人工删除会比拟很不便。粒度越小,如果是人工删除,须要先确认这个资源是否别其余页面援用,是的话则须要保留,否的话能够删除。 碍于人工删除细粒度的资源须要比拟消耗工夫和精力。心愿写一个脚本来实现这个性能。想起文件依赖,就很容易联想到 webpack 原理的 构建阶段 对 module 的依赖剖析。 webpack 在初始换编译环境之后: 内置插件 EntryPlugin 依据 entry 配置找到入口 main.js 文件,调用 compilation.addEntry 函数触发构建流程调用对应的 loaders 转译成 javascript 文本再通过 acorn 解析成 AST 树,进行遍历 AST 树,监听 import 对应的钩子,失去对应的资源依赖,调用 module 的 addDependency 将依赖增加到以后 module 的依赖列表对于新增的依赖,回到第 2 步持续解决如果咱们能够拿到 webpack 帮咱们做好的 依赖文件列表,再比照 src 目录上面的文件,如果文件不在 依赖文件列表,就收集起来,而后删除掉。 代码实现const glob = require('glob');const path = require('path');const fs = require('fs')class FileShaking { constructor(options) { this.options = { excludeRegex: [ /readme\.md/i, // 不删除readme文件 /utils/ // 不删除工具办法目录下的文件 ], delete: false, ...options }; this.fileDependencies = []; this.srcFiles = []; this.toDelFiles = []; } apply (compiler) { compiler.hooks.afterEmit.tap("FileShaking", (compilation) => { this.fileDependencies = Array.from(compilation.fileDependencies).filter(path => !path.includes('node_modules')); this.deleteIndependence(); }); } async deleteIndependence () { this.srcFiles = await this.getSrcFiles(); this.srcFiles.forEach(filePath => { if (!this.fileDependencies.includes(filePath) && !this.matchExclude(filePath)) { this.toDelFiles.push(filePath) } }) if (this.options.delete) { this.delFiles(); this.delEmptyDir('./src', (err) => { if (err) { console.log(err) } else { console.log('删除空文件夹DONE') } }); } } getSrcFiles () { return new Promise((resolve, reject) => { glob('./src/**/*', { nodir: true }, (err, files) => { if (err) { reject(err) } else { let out = files.map(file => { let tmpFilePath = path.resolve(file); return tmpFilePath.slice(0, 1).toUpperCase() + tmpFilePath.slice(1); }); resolve(out) } }) }) } matchExclude (pathname) { let matchResult = false; if (this.options.excludeRegex.length) { for (let i = 0; i < this.options.excludeRegex.length; i++) { if (matchResult = this.options.excludeRegex[i].test(pathname)) { return matchResult } } } return matchResult; } delEmptyDir (dir, cb) { fs.stat(dir, (err, stat) => { if (err) { cb(err) return; } if (stat.isDirectory()) { fs.readdir(dir, (err, objs) => { objs = objs.map(item=>path.join(dir,item)); if (err) { cb(err) return } if (objs.length === 0) { return fs.rmdir(dir, cb) } else { let count = 0 function done(...rest) { count++; if (count === objs.length) { cb(...rest); } } objs.forEach(obj => { this.delEmptyDir(obj, done) }) } }) } }) } delFiles () { this.toDelFiles.forEach(item => { fs.unlink(item, (err) => { console.log(err) }); }) console.log('删除文件DONE') }}module.exports = FileShaking;以上代码已放到我的github: https://github.com/Rockergmai... ...

March 4, 2022 · 2 min · jiezi

关于webpack:如何优雅的修改nodemodules中的依赖库

1、批改本地依赖代码并生成patch文件1.本地装置patch-package npm i patch-package2.在package.json 的scripts中退出 { "postinstall": "patch-package" },这是npm的一个钩子,会在依赖包被install之后执行 3.批改node_modules中的代码 4.生成patches npx patch-package your-edited-package-name5.提交patches后,从新install包你就会发现是你批改后的后果 2、批改部署配置:不应用缓存依赖管理员权限执行如果没有--unsafe-perm,会呈现报错,导致patch替换不胜利。参考文章: https://www.notion.so/node_mo...https://www.notion.so/node_mo...

March 3, 2022 · 1 min · jiezi

关于webpack:彻底搞懂webpack原理

loader和webpack机制webpack打包原理 ? 看完这篇你就懂了 !webpack 手写 loader 与 plugin,手写繁难版本的 webpack 手写简易版webpack

February 27, 2022 · 1 min · jiezi

关于webpack:webpack打包js文件的分析

在应用webpack中的我的项目的时候,咱们能够应用esModule,也能够应用commonJS,还能够应用import(moduleName)进行模块的懒加载,那么这所有webpack是怎么做到的呢? 1、筹备工作1.1、 应用webapck@4 webpack-cli@3"html-webpack-plugin": "4","webpack": "4","webpack-cli": "3"1.2、 文件构造 1.3、 webpack.config.jsconst path = require('path')const HtmlWebpackPlugin = require('html-webpack-plugin')const { CleanWebpackPlugin } = require('clean-webpack-plugin')module.exports = { devtool: false, mode: 'development', entry: './src/index.js', output: { filename: 'js/[name].js', path: path.resolve(__dirname, 'dist') }, plugins: [ new CleanWebpackPlugin(), new HtmlWebpackPlugin({ template: './src/index.html', }) ], optimization: { chunkIds: 'named', splitChunks: { cacheGroups: { commons: { test: /[\\/]node_modules[\\/]/, name: 'vendors', chunks: 'all', }, }, } }}1.4、打包命令npx webpack 或者 在package.json中增加 ...

February 25, 2022 · 4 min · jiezi

关于webpack:前端构建工具webpack原理篇

目标:理解输出打包命令后产生了什么事件实质:Node去运行一个js文件,这个js文件做的事件就是铺垫好流程,接着启动打包流程。首先咱们先来理解一下这个js文件到底有什么货色,再来引出概念。我把这个文件形容为一个车间,那么车间最重要的是什么呢,最重要的是要有机床。这个机床在webpack构建中称之为Compiler。它是一个编译类。 那么这个机床要须要启动的话要先筹备什么,须要先输出它该怎么运行的参数。这个参数就是咱们编写的webpack.config.js配置文件。也还须要其余shell配置。 输出完参数,接着咱们须要在机床上装置一些机械手去管制整机变动,这些机械手就是它的插件。称为Plugin。 加载完插件后,机床(编译器Compiler)就能够开始工作了。 这个在webpack整个外围的打包外围阶段称之为初始化阶段。即 1.创立编译器对象(new Compiler()); 2.初始化参数(options); 3.初始化编译环境(加载插件Plugin);** 4.开始编译(compilere.run);** 那这个编译器怎么工作的。首先这个车床它之前曾经筹备好了参数和设施,那么当初就该有某个货色推着这些整机往前走,这个货色就是滚动带。在webpack外面叫Compilation。它代表了单次构建过程。由它来推动着打包过程。 它是如何推动这个过程呢?首先咱们须要确定好入口处在哪里,而后从这里开始加载,指标就是生成一个入口模块对象。 在生成模块过程中须要将有些整机转换成可加工的模式,因为在webpack只能辨认js文件,所以咱们在构建过程中把其余资源文件例如css,sass,png等格局的文件进行解决转换成可加工的模式。这个过程须要用到的就是Loader(加载器)。Loader能将这些资源文件进行解决解析,成为可被进行解决的模式。这些加载器是从哪里来的呢,就是咱们在一开始初始化参数时定义的。Compilation会从编译器那边拿到这些loader的信息进行解决最初将模块本义成规范的js内容。 接着这些整机能够解决了,然而横七竖八的整机让机器不好解决,咱们须要将这些整机都分割到一起。(即找到它们所有的依赖关系)但想要找到这个整机须要用到哪个整机进行组件都不晓得从哪看起。这时咱们就须要先让整机序列化,能按图索骥的去操作它。用到了babel/paser将它们解析成AST对象。 略微解释一下AST,它叫做形象语法树(abstract syntax code,AST)是源代码的形象语法结构的树状示意。简而言之,它能够示意源代码中的每一个构造。例如: 有了Ast对象,当初就能够获取这个模块对应的依赖。 怎么获取这个模块对应的依赖呢?babel/traverse这个工具能够通过import/require语句来进行判断。这时找到入口文件所须要的依赖之后注入到依赖数组中,生成一个含有文件名,ast对象,依赖数组的入口模块。接着在反复上述步骤递归去找到入口模块下的依赖对应的依赖。这时将所有的整机都分割起来。 开展说一下找寻依赖关系的步骤,如果入口文件的依赖关系如下: 通过加工后造成入口模块流程如下: 这时compliation会顺次去遍历这两个依赖文件,生成对应的模板: 因为a.js文件下仍有依赖文件,所以compliation会持续遍历,直到没有新的依赖为止: 这个阶段在webpack整个外围的打包外围阶段称之为构建阶段。1.编译模块(make);loader解析,生成ast对象,构建入口模块。2.实现模块编译;找到入口模块下的所有依赖关系,生成不同模块。 此时咱们把一个个整机加工好了,也把它们之间的关系表明了,最初就是要将它们包装起来。这时须要用的包装纸,在webpack外面叫做chunk。依照肯定的规定分成一个个chunk,一个chunk能够蕴含一个模块或者多个模块。将一个个chunk增加到输入列表中去。最初调用node的文件流(fs),依据配置好的进口门路和文件名,把文件写到文件系统中去生成一个js打包文件。 这个阶段在webpack整个外围的打包外围阶段称之为生成阶段。即1.输出资源(seal);依据依赖关系生成一个个chunk,增加到输入列表。2.写入文件系统;依据配置进口门路和文件名,进行写入。 整体的文件状态流转: 总结webpack根本的构建流程大体上如上述所示,然而还有波及的很多细节无奈进行逐个开展,但了解了大略的流程会对webpack有一个新的意识,它之所弱小是因为这条流程根本是不变的,而且拓展性强,它利用loader,plugin插件来一直壮大它的生态,成为了前端一个不那么容易被代替的构建工具。

February 14, 2022 · 1 min · jiezi

关于webpack:webpack5优化的地方及搭建的一些体会

前言在从Webpack4到Webpack5的降级过程中,即便以前曾经搭建过Webpack4,然而搭建Webpack5的过程中还是有点苦楚。因为Webpack提供的性能办法切实是太多了,很宏大的一个体系,所以搭建完感触还是很多的,发现不能一味的从网上找,还是得看文档。 看完文档才发现原来Webpack5外面曾经精简了很多插件了,不须要额定装置其余插件,很多以前概念比拟含糊的货色,看了文档还是比拟清晰的。大家有趣味的话能够Fork我的webpack5-boilerplate学习交换,倡议大家多敲敲多试试,过程尽管有点苦楚,然而肯定会有播种的。 本文解说,须要肯定Webpack4根底,还没有搭建过Webpack4的同学,能够看看这篇Webpack4搭建 上面的解说,都基于webpack5-boilerplate这个我的项目。 Webpack大体框架首先咱们对Webpack得有一个大体的框架意识 // webpack.config.jsmodule.exports = { // 入口 entry: {}, // 打包输入 output: {}, // 配置模块如何解析 resolve: {}, // 配置各种loader moudle: {}, // 配置插件 plugins: [], // 优化(能够进行代码宰割) optimization: {}, // webpack-dev-server 开发时的配置,个别用于development模式 devServer: {}};所须要的LoaderCSS类的Loadercss-loadercss-minimizer-webpack-pluginmini-css-extract-pluginless-loaderlessstyle-loader...目前我临时用到的就这些 解析ES6类的Loader@babel/core@babel/plugin-transform-runtime@babel/preset-envbabel-loadercore-js解析Html类的Loaderhtml-webpack-pluginWebpack5不须要用到的依赖url-loaderfile-loaderclean-webpack-plugin@babel/polyfill@babel/runtimeoptimize-css-assets-webpack-plugin最初依赖列表预览"devDependencies": { "@babel/core": "^7.16.12", "@babel/plugin-transform-runtime": "^7.16.10", "@babel/preset-env": "^7.16.11", "babel-loader": "^8.2.3", "css-loader": "^6.5.1", "css-minimizer-webpack-plugin": "^3.4.1", "filemanager-webpack-plugin": "^6.1.7", "html-webpack-plugin": "^5.5.0", "less": "^4.1.2", "less-loader": "^10.2.0", "mini-css-extract-plugin": "^2.5.3", "style-loader": "^3.3.1", "webpack": "^5.67.0", "webpack-cli": "^4.9.2", "webpack-dev-server": "^4.7.3", "webpack-merge": "^5.8.0"},"dependencies": { "core-js": "^3.20.3"},webpack5-boilerplate这个脚手架,外围的就这些依赖,另外须要的依赖再本人装就好了。是不是感觉依赖少了很多,我是登时感觉很难受。接下来讲一下这些不须要用到的插件,如何在Webpack5外面用别的形式代替。应用Asset Module模块,来治理资源官网解释:资源模块(asset module)是一种模块类型,它容许应用资源文件(字体,图标等)而无需配置额定 loader。以编译图片为例,所以如果咱们要编译图片: ...

February 14, 2022 · 2 min · jiezi

关于webpack:webpack-5-模块联邦实现微前端

webpack 5 模块联邦实现微前端微前端:将微小的单体前端零碎拆分成多个独立的小型零碎,最初集成为一个零碎的架构思路,分而治之,让零碎更加容易保护、更易扩大,施行微前端是一个先拆分,后合并的过程。 这里的前端利用指的是前后端拆散的单页利用,在这根底上议论微前端才有意义。 微前端和微服务都是为了解决大我的项目和大团队的难题:大我的项目实现模块解耦,大团队实现人员解耦,这两大难题是《软件工程》这门课程钻研的次要问题。 康威定律:软件结构体现人员构造,人员构造决定软件结构造。 阮一峰软件工程介绍 微服务架构的实践根底 - 康威定律 康威定律 为何须要微前端巨石单体零碎随着业务的减少,变得越来越臃肿,多个团队一起开发,沟通胜利高,编译、部署、测试、保护艰难,微前端可解决这些问题。 利用自治:各个利用互相独立,规模更小,更容易扩大、测试、构建、保护、排错、降级依赖等;团队自治:利用独立后,团队也会独立,缩小很多人在一个巨石利用中同时开发,相互影响,进步开发效率;技术无关:各个利用可抉择不同的框架开发,尽量放弃对立,否则利用之间交互会可能遇到麻烦,也不利于组件复用,比方无奈共享组件级别的代码;尝试新技术:利用拆分后,很容易在零碎里尝试新技术。老零碎增量重构。毛病: 代码标准对立比拟艰难(人员多、我的项目多),容易克服开发时可能须要同时运行多个我的项目,容易克服集成测试比拟艰难UI、交互等容易不对立,容易克服相比微前端的长处,毛病根本可忽略不计。 施行倡议: 统一的工作办法:团队成员要达成统一的工作办法,尤其是宿主利用和近程利用之间的交互协定,须要提前约定好;联合业务:在应用为微前端架构之前,思考业务划分和微前端给团队给来的价值;听从统一的代码格调,不便前期保护;不要适度应用:心愿能实现拆分人员或者技术的指标,或者有必要拆分人员或者技术时才应用。微前端介绍 对于微前端最早的探讨文章 如何集成 --- 聚合次要三种集成形式: 集成形式具体形容长处毛病其余构建时集成把微利用打包进入主利用,微利用通常以 npm 包公布施行容易且很好了解有依赖关系的利用之间,其中一个更新,另一个也要更新,而后部署,实际上无奈独立部署实际上这种形式并没有实现微前端的指标运行时构建主利用在浏览器加载后,再去获取微利用代码独立部署,主利用能决定应用哪个微利用的版本,灵便,性能好设置简单,不好了解实现微前端的指标,目前比拟通用的形式服务端集成主利用向服务器申请微利用,服务器决定是否给代码重大依赖后盾代码实现简单,个别不应用 集成时须要思考哪些问题? 防止款式抵触利用之间通信简略不同利用之间导航丝滑能集成特定版本版本控制不互相烦扰能不便实现依赖共享常见的微前端实施方案微前端的架构形式呈现后,业界呈现一些框架和解决方案,常见的: 框架: MicroApp 、single-spa、qiankuan 无裤架的解决方案: web components 不举荐,无奈提供模块化性能,我的项目越大,越容易失控,web component 实质是封装自定义的 html,会很快会到 jQuery 时代。 iframe webpack5 module federation 模块联邦,webpack5 的一个新个性,可实现跨利用共享代码。 如何拆分微利用?在拆分时,心愿不同利用之间的交互最小为准则,最大水平解耦,以不便不同利用之间的通信,否则导致利用难以测试、问题难以定位。 依照业务划分,雷同的业务拆分到同一个微利用中。 依照权限划分,依据用户的权限,不同用户应用应用的性能划分到一起。 依照后盾微服务划分,有的团队,后盾应用微服务架构,可思考依照微服务划分。 模块联邦 -- Module Federation模块联邦是 webpack5 引入的个性,能轻易实现在两个应用 webpack 构建的我的项目之间共享代码,甚至组合不同的利用为一个利用。 Module Federation 官网 模块联邦的配置模块联邦可实现跨利用共享代码,以两个利用为例子阐明其配置。 一个dashboard vue3 利用,心愿提供代码给其余利用: // const ModuleFederationPlugin = require('webpack/lib/container/ModuleFederationPlugin') // 导出模块联邦const { ModuleFederationPlugin } = require('webpack').container // 还能够这样// webpack 插件配置{plugins: [ new ModuleFederationPlugin({ name: 'dashboard', // exposeRemoteName 共享的模块名字,在生产该模块的利用中会用到 不能应用 - filename: 'remoteEntry.js', // 近程加载的文件名字,在浏览器申请面板可看到,默认名字就是 remoteEntry.js exposes: { './DashboardApp': './src/bootstrap', // 从本利用裸露的共享模块,可共享多个模块 key 以 ./ 结尾,value 指向本地的一个文件 }, shared: packageJson.dependencies, // 心愿共享的依赖 }), ],}对于名字的设置name 的值会被导出成一个全局变量,不要应用-,不要和页面里的 id 雷同,否则可能报错。 ...

January 24, 2022 · 9 min · jiezi

关于webpack:webpack总结

devtooltree shakingtree shaking 是一个术语,通常用于形容移除 JavaScript 上下文中的未援用代码(dead-code)。它依赖于 ES2015 模块零碎中的动态构造个性,例如 import 和 export。最早由rollup实现。 tree shaking的原理ES6 Module引入进行动态剖析,故而编译的时候正确判断到底加载了那些模块动态分析程序流,判断那些模块和变量未被应用或者援用,进而删除对应代码// testexport const name = 123;export const age = 9999;//index.jsimport {name, age} from './test.js';console.log(name);webpack.config.jsconst path = require("path");module.exports = { mode: "development", entry: "./src/index.js", output: { filename: "bundle.js", path: path.resolve(__dirname, "dist"), }, optimization: { usedExports: false }, devtool: "cheap-source-map" // 为了不便查看编译后的源码};编译后: /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "name", function() { return name; });/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "age", function() { return age; });optimization.usedExports通知webpack为每个模块确定应用的导出 ...

January 12, 2022 · 1 min · jiezi

关于webpack:webpack处理-static静态资源文件压缩混淆

我的项目中会依赖一些开源JS-SDK 因为革新源码export工作量比拟大 因而只能放在static在html用script标签援用,同时心愿这些源码文件参加压缩混同 1.npm 装包npm i uglify-es 2.build/webpack.prod.conf.js增加配置 const UglifyJS = require('uglify-es') //援用uglify-es插件进行压缩混同代码new CopyWebpackPlugin([{ from: path.resolve(__dirname, '../static'), to: config.build.assetsSubDirectory, ignore: ['.*'] }, {//指定文件夹下所有js文件到指定文件夹 from: path.resolve(__dirname, '../static/one/js'), to: './static/one/js', transform: function (content) { return UglifyJS.minify(content.toString()).code; } }, {//指定单个文件到指定文件夹 from: path.resolve(__dirname, '../static/two/js/test.js'), to: './static/two/js/', transform: function (content) { return UglifyJS.minify(content.toString()).code; } } ])注:本文系转载,更多计划请参考原作者:https://juejin.cn/post/684490...

January 5, 2022 · 1 min · jiezi

关于webpack:自动化构建工具二特性

如何实现文件监听--watch文件源码变动时,主动从新构建输入新的编译文件。(热重载)须要每次手动刷新浏览器原理:通过“不停轮询文件的批改工夫“,缓存一批更新 watchOptions: { ignored: /node_modules/, aggreagteTimeout: 300, // 监听到变动后等300ms后再去执行,默认300ms poll: 1000 // 每1000ms查看一次变动}以上只是达到了热重载,要想热更新,须要配合webapck-dev-server和HotModuleReplacementPlugin实现。

January 4, 2022 · 1 min · jiezi

关于webpack:浅谈-webpack-一

1.babel-loader将 js 代码转换为低版本,来看看解释Babel 是一个工具链,次要用于将 ECMAScript 2015+ 版本的代码转换为向后兼容的 JavaScript 语法,以便可能运行在以后和旧版本的浏览器或其余环境中。 npx webpack --mode=development执行webpack打包 webpack 次要由几局部组成cli 模块 Node Loader plugin 1.CLI 构建(build)配置和交互 2.模块:webpack 用于解决不同模块之间的打包 3.Node:对编译粒度的更细管制须要通过Node接口实现 4.Loader:转译模块源代码规定-承受源代码作为参数的函数 5.plugin:插件 察看模式 --npm run watch更改文件时不须要从新打包运行整个文件 始终保持着察看变动的文件 更新打包 webpack-dev-server 提供一个简略的服务器,实现从新加载(防止手动去加载刷新浏览器)

December 16, 2021 · 1 min · jiezi

关于webpack:Webpack-优化开发体验

Webpack Dev Server集成了 主动编译 和 主动刷新浏览器 等性能。webpack-dev-server 在编译之后不会写入到任何输入文件,而是将 bundle 文件保留在内存中,而后将它们 serve 到 server 中。 yarn add webpack-dev-server --devconst path = require("path");const { CleanWebpackPlugin } = require("clean-webpack-plugin");const HtmlWebpackPlugin = require("html-webpack-plugin");const CopyWebpackPlugin = require("copy-webpack-plugin");module.exports = { mode: "development", entry: "./src/main.js", output: { filename: "bundle.js", path: path.join(__dirname, "dist"), }, module: { rules: [ { test: /.css$/, use: ["style-loader", "css-loader"], }, { test: /.png$/, use: { loader: "url-loader", options: { limit: 10 * 1024, }, }, }, ], }, plugins: [ new CleanWebpackPlugin(), new HtmlWebpackPlugin({ title: "Ideal Webpack Develop Env", meta: { viewport: "width=device-width", }, template: "./src/index.html", }), // 开发阶段最好不要应用这个插件,频繁复制动态资源文件 // new CopyWebpackPlugin({ // patterns: ["public"], // }), ], devServer: { // 指定额定动态资源文件门路 contentBase: ["./public"], proxy: { "/api": { // http://localhost:8080/api/users -> https://api.github.com/api/users target: "https://api.github.com", // http://localhost:8080/api/users -> https://api.github.com/users pathRewrite: { "^/api": "", }, }, }, },};yarn webpack serve --openSource MapSource map 就是一个信息文件,外面贮存着地位信息。也就是说,转换后的代码的每一个地位,所对应的转换前的地位。 ...

November 30, 2021 · 4 min · jiezi

关于webpack:webpack-起步

webpackwebpack 就是一个前端资源打包工具,它依据模块的依赖关系进行动态剖析,而后将这些模块依照指定的规定生成对应动态资源。 根本应用在本地装置 webpack yarn add webpack webpack-cli --dev文件目录,创立 webpack.config.js 配置文件(在 webpack v4 中,能够毋庸任何配置,然而大多数我的项目会须要很简单的设置)。 const path = require("path");module.exports = { /** * 默认值为 production * development 优化打包速度,增加一些调试过程须要的辅助 * production 优化打包后果 **/ mode: "development", entry: "./src/main.js", // 入口文件 output: { filename: "bundle.js", // 输入文件名 path: path.join(__dirname, "dist"), // 输入文件门路 },};运行打包命令 yarn webpack资源模块加载Webpack 默认只能解决 js 文件,非 js 文件通过 loader 加载解决 文件资源安装文件资源对应 loader yarn add css-loader style-loader --dev文件引入 // main.jsimport createHeading from "./heading.js";import "./main.css";const heading = createHeading();document.body.append(heading);webpack 配置文件 ...

November 30, 2021 · 4 min · jiezi

关于webpack:htmlpluginwebpack模板内容高度定制化

应用html-plugin-webpack时个别都会设置template属性配置html模板。 但这存在毛病: 在团队领有多个我的项目时, html格局的模板内容无奈做到通用性能的对立和针对特定我的项目的扩大。所以如果将模板内容的配置为js内容,获取js的齐全编码能力, 既能够封装团队中我的项目通用模板内容, 有保障较高的定制能力. 本文中应用的是html-plugin-webpack版本是v3版本。v4版本反对更多的选项反对本文的内容,而不是通过插件实现。下文就以html模板中罕用改用为js代码怎么配置. 页面题目如果不配置html-webpack-plugin的template选项, 配置title选项时, 生成的html文件中将会有题目: module.exports = {  // ...  plugins: [    new HtmlWebpackPlugin({      title: '测试',    }),  ],};生成的文件中:   <head>    <meta charset="UTF-8">    <title>测试</title>  </head>图标设置favicon选项, html-plugin-webpack会主动将图片文件复制到output目录下, 而后应用, 会主动增加上publicPath. module.exports = { // ...  plugins: [    new HtmlWebpackPlugin({      favicon: './build/favicon.ico',    }),  ],};生成的html代码中: <link rel="shortcut icon" href="https://you.com/path/to/favicon.ico">对于挪动端利用, 图标配置举荐应用favicons-webpack-plugin.设置meta信息html文件中通常须要设置许多meta信息, 通过html-webpack-html的meta选项, 能够生成这些meta信息, 如: module.exports = { // ...  plugins: [    new HtmlWebpackPlugin({      meta: {        author: 'xxx前端团队',      },    }),  ],};如果须要配置http-equiv相干, 须要以下语法: ...

November 20, 2021 · 4 min · jiezi

关于webpack:webpack的chunk生成逻辑

刚接触webpack时,应用webpack打包后只会生成一个被称为bundle的文件,在缓缓相熟webpack后,如果同时对于前端优化有肯定的理解,就会尝试将臃肿的bundle拆分成多个小文件并按需加载。 本文心愿通过对webpack的局部配置进行阐明,让读者对相干的操作有肯定理解和把握。以下操作均是在webpack@4环境下的阐明。 webpack中通过配置的optimization.splitChunks来实现这样的成果,该配置也是SplitChunksPlugins插件的配置。 webpack为optimization.splitChunks提供了默认值,让咱们来看看: // // ** 默认的splitChunks内容 **//{ chunks: 'async', minSize: 30000, maxSize: 0, minChunks: 1, maxAsyncRequests: 5, maxInitialRequests: 3, automaticNameDelimiter: '~', automaticNameMaxLength: 30, name: true, cacheGroups: { vendors: { test: /[\\/]node_modules[\\/]/, priority: -10 }, default: { minChunks: 2, priority: -20, reuseExistingChunk: true } }};让咱们来认真看看其中的配置 chunks通过配置该项,开发者能够抉择须要进行优化的chunk,被选中的chunk,其中的modules将被剖析,并依照肯定的策略生成新的chunk。 容许all、async、initial、(chunkname) => boolean四种值,具体成果如下: initial: 所有的立刻加载的chunk(例如bundle文件)将被查看async: 所有提早加载的chunk将被查看all: 等价于initial + async成果,所有的chunk都将被查看(chunkname) => boolean: 函数模式能够提供更细粒度的管制默认状况为async,所以咱们的bundle不会被优化,这里能够尝试批改为initial之后再进行一次编译。 { chunks: 'initial',}除了生成bundle之外,可能还会有名为vendors~xxx.js的文件。(如果没有生成的话,能够尝试在代码中引入node_modules中的包,再从新编译后查看后果。) 两次编译后果的变动,即chunks从async变为initial后,bundle文件因作为一个立刻加载的chunk而被优化了。 minSize、maxSize见名知意,minSize和maxSize限定了新生成的chunk的文件的最小/最大尺寸。只有当筹备生成的chunk的最大和最小文件尺寸,只有在这个尺寸内的chunk文件才会被生成,否则代码会放弃原样。 minSize=30000示意chunk最小应该有30000bytes。maxSize=0示意不限度chunk的最大尺寸。如果设置为一个其余的正当值,例如150000,生成的chunk超过了maxSize的状况下,该chunk将被进一步拆分成更小的chunk。 cacheGroupscacheGroups是splitChunks配置的一个要害配置,其决定了module应该如何合并成一个新的chunk。 { vendors: { test: /[\\/]node_modules[\\/]/, priority: -10 },}在cacheGroups配置下的每一个对象,都能够认为是一个cacheGroup,例如下面的代码中是key为vendors的对象。 ...

November 13, 2021 · 1 min · jiezi

关于webpack:Webpack-原理系列九TreeShaking-实现原理

一、什么是 Tree ShakingTree-Shaking 是一种基于 ES Module 标准的 Dead Code Elimination 技术,它会在运行过程中动态剖析模块之间的导入导出,确定 ESM 模块中哪些导出值未曾其它模块应用,并将其删除,以此实现打包产物的优化。 Tree Shaking 较早前由 Rich Harris 在 Rollup 中率先实现,Webpack 自 2.0 版本开始接入,至今曾经成为一种利用宽泛的性能优化伎俩。 1.1 在 Webpack 中启动 Tree Shaking在 Webpack 中,启动 Tree Shaking 性能必须同时满足三个条件: 应用 ESM 标准编写模块代码配置 optimization.usedExports 为 true,启动标记性能启动代码优化性能,能够通过如下形式实现: 配置 mode = production配置 optimization.minimize = true提供 optimization.minimizer 数组例如: // webpack.config.jsmodule.exports = { entry: "./src/index", mode: "production", devtool: false, optimization: { usedExports: true, },};1.2 实践根底在 CommonJs、AMD、CMD 等旧版本的 JavaScript 模块化计划中,导入导出行为是高度动静,难以预测的,例如: ...

October 15, 2021 · 4 min · jiezi

关于webpack:webpack-流程解析1创建compiler之前

前言compiler对象是一个全局单例,它负责把控整个webpack打包的构建流程。本文将会介绍在 new compiler 之前,webpack做了什么 启动webpack通常状况下,咱们应用如下形式来启动webpack // package.jsonscript: { "start": "webpack"}webpack/bin运行 npm run start 之后,会先进入 webpack/bin 下, webpack应用 isInstalled("webpack-cli")来判断是否装置了cli, 没装置会应用 yarn 或者 npm 帮你装置,最初会走到runCli这个办法,外围代码就一句 require(path.resolve(path.dirname(pkgPath), pkg.bin[cli.binName]));这里去读取 webpack-cli/bin/cli.js。 webpack-cli/binwebpack-cli/bin/cli.js 竟然还要判断一下是否装置了 webpack(下面不是判断过了), 如果没装置再帮你装置一下,而后就是实例化一个 webpack-cli 对象,执行实例的run办法。这外面代码就不细说了,其实就干了两件事: 拿到process.args 的参数,校验合并参数,针对args的值给webpack的config减少对应的plugin最初拿到了参数又调用了webpack。 这里用了两个包来进步运行效率,一个是 import-local,用于优先应用本地文件,另一个是 v8-compile-cache, 用来做 v8 的编译缓存优化。后续咱们再聊这两个回到webpack回到webpack之后呢,就要开始创立 compiler 实例啦,在这之前,其实也会有一点分支逻辑须要解决 如果参数是一个数组,就创立MultiCompiler实例, 否则就创立一个Compiler的实例。参数的校验和复制默认值所有都走完之后,就要开始创立 compiler 对象了。 结语在创立 compiler 对象之前 webpack 做的事件并不多。简略说就一句话,筹备好参数。同时也有一些性能优化的伎俩,这些不在本次系列的探讨范畴内,当前有工夫再和大家分享

October 7, 2021 · 1 min · jiezi

关于webpack:谈下-webpack-loader-的机制

残缺高频题库仓库地址:https://github.com/hzfe/awesome-interview 残缺高频题库浏览地址:https://febook.hzfe.org/ 相干问题webpack loader 是如何工作的如何编写 webpack loader答复关键点转换 生命周期 chunk webpack 自身只能解决 JavaScript 和 JSON 文件,而 loader 为 webpack 增加了解决其余类型文件的能力。loader 将其余类型的文件转换成无效的 webpack modules(如 ESmodule、CommonJS、AMD),webpack 能生产这些模块,并将其增加到依赖关系图中。 loader 实质上是一个函数,该函数对接管到的内容进行转换,返回转换后的后果。 常见的 loader 有: raw-loader:加载文件原始内容。file-loader:将援用文件输入到指标文件夹中,在代码中通过相对路径援用输入的文件。url-loader:和 file-loader 相似,然而能在文件很小的状况下以 base64 的形式将文件内容注入到代码中。babel-loader:将 ES 较新的语法转换为浏览器能够兼容的语法。style-loader:将 CSS 代码注入到 JavaScript 中,通过 DOM 操作加载 CSS。css-loader:加载 CSS,反对模块化、压缩、文件导入等个性。应用 loader 的形式次要有两种: 在 webpack.config.js 文件中配置,通过在 module.rules 中应用 test 匹配要转换的文件类型,应用 use 指定要应用的 loader。module.exports = { module: { rules: [{ test: /\.ts$/, use: "ts-loader" }], },};内联应用import Styles from "style-loader!css-loader?modules!./styles.css";知识点深刻1. 编写 webpack loader1.1 同步 loader同步转换内容后,能够通过 return 或调用 this.callback 返回后果。 ...

October 1, 2021 · 6 min · jiezi

关于webpack:Webpack-5540-发布重要更新汇总

webpack 是一个模块打包器。webpack 的次要指标是将 javaScript 文件打包在一起,打包后的文件用于在浏览器中应用,但它也可能胜任转换(transform)、打包(bundle)或包裹(package)任何资源(resource or asset)。 Webpack 5.54.0 次要更新内容如下: 个性 改良常量折叠以容许跳过更多 && || 和 ?? 分支容许在 webpack 中应用所有的 hashing ,用 output.hashFunction 进行配置在模块中应用 eval 时,不再齐全从外部图剖析中跳出Bug 修复 force bump enhanced - 解决谬误的办法性能 缩小创立 snapshots 时的调配量增加一个基于 wasm 的超疾速哈希函数 output.hashFunction: "xxhash64"改良短字符串序列化时的 utf-8 转换进步依赖项的 hashing 性能增加 experiments.cacheUnaffected,用户缓存未更改模块的计算并仅援用未更改模块更新阐明:https://github.com/webpack/we...

September 26, 2021 · 1 min · jiezi

关于webpack:关于多模块部署流程的多配置打包优化

针对大型项目中,功能模块拆解成子模块利用,独立开发、部署、打包,但又存在公共配置和利用库,搜查及实际了一套基于webpack的利用开发计划 一、共享公共库但模块独立原理我的项目开发过程中1.通过实现一个modules配置文件注册独立模块的文件门路及设定的各项可配置参数,通过配置启动命令额定参数,在webpack.config.js,获取process.argv中所需的模块id,而后获取该模块的公有配置,可简略将可配置项置入modules.json中,也能够设定在模块门路内设置独有的webpack.private.js文件作merge操作。2. 二、打包计划办法劣势多入口entry轻易共享配置代码module.exports多种配置导出灵便配置各个模块的配置项 可同时编译,应用parallelism管制并发数Node child_process子过程打包,并发充分利用系统资源、打包速度快

September 14, 2021 · 1 min · jiezi

关于webpack:长文玩转-webpack-学习笔记

写在最后面最近工作中webpack用的比拟多,想零碎的学习一下,找到了极客工夫的教程,跟着视频上讲的学了一遍,播种挺大的。尽管视频教程是2019年出的,有点老,有些常识曾经过期了,但并不障碍学习。那些过期的常识全当理解,能够搜寻寻找代替计划。学习资源:玩转webpack,上面是我的学习笔记。 构建工具前端技术一直倒退,比方:React的jsx,Vue和Angular指令,CSS预处理器,最新的ES语法等,浏览器都不能辨认。 构建工具的作用就是将这些浏览器不能辨认的语法(高级语法)转换成了浏览器能辨认的语法(低级语法)。 还有一个作用是将代码压缩混同,在压缩代码体积的同时也让代码不易浏览。 webpack是当初前端风行的构建工具。 初识webpack配置script脚本装置好webpack后,在命令行中应用webpack时,有两种形式: 指定门路./node_modules/.bin/webpack应用npx工具,npx webpack这两种办法应用挺麻烦的。有种简略的形式应用package.json中的scripts,它可能读到node_modules/.bin目录下的命令。 在命令行中执行npm run build即可。 "scripts": { "build": "webpack"}配置文件webpack的默认配置文件webpack.config.js,能够通过webpack --config来指定配置文件。 比方,生产环境的配置文件webpack.config.prod.js,开发环境的配置文件是webpack.config.dev.js。 "scripts": { "build": "webpack --config webpack.config.prod.js", "build:dev": "webpack --config webpack.config.dev.js"}外围概念webpack有 5 个外围概念:entry、output、mode、loaders、plugins。 entry打包时的入口文件,默认是./src/index.js entry是有两种形式:单入口、多入口。 单入口用于单页面利用,entry是个字符串 module.exports = { entry: "./src/index.js",};多入口用于多页面利用,entry是对象模式 module.exports = { entry: { index: "./src/index.js", app: "./src/app.js", },};output打包后的输入文件,默认是./dist/main.js。 entry是单入口,output可通过批改参数path和filename。 const path = require("path");module.exports = { entry: "./src/index.js", output: { path: path.resolve(__dirname, "dist"), filename: "index.js", },};entry是多入口,output的filename须要用[name]占位符,用来指定打包后的名称,对应的是entry中的key const path = require("path");module.exports = { entry: { index: "./src/index.js", app: "./src/app.js", }, output: { path: path.resolve(__dirname, "dist"), filename: "[name].js", },};mode可设置为development、production、none,默认是production。 ...

September 7, 2021 · 7 min · jiezi

关于webpack:你真的会用devServer这个配置项嘛

devServer通过 webpack-dev-server 的这些配置,可能以多种形式扭转其行为。这是一个根本的示例,利用 gzips 压缩 dist/ 目录当中的所有内容并提供一个本地服务(serve): devServer: { contentBase: path.join(__dirname, "dist"), compress: true, port: 9000}参数阐明devServer: { // 提供动态文件目录地址 // 基于express.static实现 contentBase: path.join(__dirname, "dist"), // 将此项配置设置为 true 时,将会跳过 host 查看。这是不举荐的因为不查看 host 的利用容易受到 DNS 从新绑定攻打 disableHostCheck:true, // 在所有响应中增加首部内容 headers: { "X-Custom-Foo": "bar" }, // 当启用 lazy 时,dev-server 只有在申请时才编译包(bundle)。这意味着 webpack 不会监督任何文件改变。咱们称之为“惰性模式” lazy:true, // 任意的 404 响应都被代替为 index.html // 基于node connect-history-api-fallback包实现 historyApiFallback: true, // 是否所有服务都启用 gzip 压缩 // 基于node compression包实现 compress: true, // 是否暗藏bundle信息 noInfo: true, // 产生谬误是否笼罩在页面上 overlay: true, // 是否开启热加载 // 必须搭配webpack.HotModuleReplacementPlugin 能力齐全启用 HMR。 // 如果 webpack 或 webpack-dev-server 是通过 --hot 选项启动的,那么这个插件会被主动增加 hot: true, // 热加载模式 // true代表inline模式,false代表iframe模式 inline: true, // 默认是true // 是否主动关上 open: true, // 设置本地url和端口号 host: 'localhost', port: 8080, // 代理 // 基于node http-proxy-middleware包实现 proxy: { // 匹配api前缀时,则代理到3001端口 // 即http://localhost:8080/api/123 = http://localhost:3001/api/123 // 留神:这里是把以后server8080代理到3001,而不是任意端口的api代理到3001 '/api': 'http://localhost:3001', // 设置为true, 本地就会虚构一个服务器接管你的申请并代你发送该申请 // 次要解决跨域问题 changeOrigin: true, // 针对代理https secure: false, // 覆写门路:http://localhost:8080/api/123 = http://localhost:3001/123 pathRewrite: {'^/api' : ''}, // 输入本次代理申请的日志信息 bypass: function (req, res, proxyOptions) { console.log(proxyOptions.target) } }}哈哈哈哈哈哈,当你看到这里的时候,你应该想多理解点,其实官网文档都有点我都有 ...

August 12, 2021 · 1 min · jiezi

关于webpack:Webpack-入门基础篇

概念Webpack 是一种前端资源构建工具,一个动态模块打包器。一个前端我的项目中蕴含了很多资源,然而浏览器并不一定全副意识,比方sass、less、ts,包含js里的高级语法。这些资源如果想在浏览器中失常工作,必须通过编译解决。而咱们的Webpack就是能够集成的解决这些文件,并且汇总到一个文件中。 Webpack外围根底entry入口(entry):代表着 Webpack 以那个文件为入口终点开始打包,剖析构建外部依赖图。默认值是 ./src/index.js,但你也能够通过配置 entry 属性,来指定一个(或多个)不同的入口终点。 module.exports = { entry: './path/to/my/entry/file.js'};output输入(output): 批示 Webpack 打包后到资源 bundles 输入到哪里,以及如何命名。次要输入文件的默认值是 ./dist/main.js,其余生成文件默认搁置在 ./dist 文件夹中。 const path = require('path');module.exports = { entry: './path/to/my/entry/file.js', output: { path: path.resolve(__dirname, 'dist'), filename: 'my-first-webpack.bundle.js' }};LoaderLoader:Webpack 本身只能了解 JavaScript 和 json 文件,loader 让 Webpack 可能解决其余文件。 const path = require('path');module.exports = { output: { filename: 'my-first-webpack.bundle.js' }, module: { rules: [ { test: /\.txt$/, use: 'raw-loader' } ] }};plugin插件(plugins):能够用于执行范畴更广的工作。从打包优化和压缩,始终到从新定义环境中的变量等。 const HtmlWebpackPlugin = require('html-webpack-plugin'); // 通过 npm 装置const webpack = require('webpack'); // 用于拜访内置插件module.exports = { module: { rules: [ { test: /\.txt$/, use: 'raw-loader' } ] }, plugins: [ new HtmlWebpackPlugin({template: './src/index.html'}) ]};mode模式(mode):批示 Webpack应用相应模式的配置。默认为production。 ...

August 9, 2021 · 1 min · jiezi

关于webpack:webpack打包相关

browserify:用于将CommonJS编译之后能够在浏览器端应用 一、mode开发环境mode:'development'生产环境mode:'production' 二、entryentry: 入口终点 string --> './src/index.js'单入口打包造成一个chunk。 输入一个bundle文件。此时chunk的名称默认是 mainarray --> ['./src/index.js', './src/add.js']多入口所有入口文件最终只会造成一个chunk, 输入进来只有一个bundle文件。--> 只有在HMR性能中让html热更新失效~object多入口有几个入口文件就造成几个chunk,输入几个bundle文件此时chunk的名称是 key--> 非凡用法 { // 所有入口文件最终只会造成一个chunk, 输入进来只有一个bundle文件。 index: ['./src/index.js', './src/count.js'], // 造成一个chunk,输入一个bundle文件。 add: './src/add.js' }三、outputoutput: { // 文件名称(指定名称+目录) filename: 'js/[name].js', // 输入文件目录(未来所有资源输入的公共目录) path: resolve(__dirname, 'build'), // 所有资源引入公共门路前缀 --> 'imgs/a.jpg' --> '/imgs/a.jpg' publicPath: '/', chunkFilename: 'js/[name]_chunk.js', // 非入口chunk的名称 // library: '[name]', // 整个库向外裸露的变量名 // libraryTarget: 'window' // 变量名增加到哪个上 browser // libraryTarget: 'global' // 变量名增加到哪个上 node // libraryTarget: 'commonjs' },filename与缓存hash,webpack每次打包都会生成新的hash值chunkhash,依据chunk生成的hash值,如果打包来源于同一个chunk,那么hash值就一样contenthash,依据文件的内容生成hash值,不同文件的hash值肯定不一样四、loaderwebpack只能解决js和json文件,其余类型文件须要loader进行编译转换成webpack可辨认的文件 ...

August 2, 2021 · 2 min · jiezi

关于webpack:基于webpack5的多页面打包

前言在理论开发要求中咱们可能无奈是应用单页面开发框架(例如vue,react),这些要求次要是基于SEO角度登程(当然能够应用服务端渲染解决,这里咱们不思考),这时候咱们就须要进行传统模式的前端开发,传统模式下会有css兼容与压缩,icon图片base64化缩小http申请,公共代码引入,js模块化等根底问题。对于wepack多页面打包的材料文档很丰盛,理论遇到问题不要惊恐能够去网上查问或者去看看官网文档(webpack文档-传送门)。本篇文章是基于最新版本的webpack来实现多页面打包的,不仅解决了上述根底问题还减少了本地服务,批改自更新,公共代码主动引入等实用功能。本文的webpack打包框架已开源至githua欢送大家的start(git-传送门) 上面咱们采纳已性能为导向的webpack5多页面打包配置介绍 性能配置篇1、初始化webpack npm initnpm install webpack webpack-cli -g // -g 更换为 --save-dev 是本地装置webpack-cli init2、图片文件及其他文件解决,webpack5集中到了asset模块, 之前应用file-loader、url-loader、raw-loader三个 asset/resource 将资源宰割为独自的文件,并导出url,就是之前的 file-loader的性能.asset/inline 将资源导出为dataURL(url(data:))的模式,之前的 url-loader的性能.asset/source 将资源导出为源码(source code). 之前的 raw-loader 性能.asset 主动抉择导出为独自文件或者 dataURL模式(默认为8KB). 之前有url-loader设置asset size limit 限度实现。配置 webpack.config.js module: { rules: [ { test: /\.(eot|svg|ttf|woff|woff2|png|jpg|gif)$/i, type: "asset", generator: { // 输入文件名 filename: 'static/[hash][ext][query]' } } ]}// 还能够限度解决的大小,这里应用了默认值3、解决html文件,为了后盾敌人好绑定不进行压缩操作,解决html里icon与资源 webpack.config.js module: { rules: [ { test: /\.html$/, loader: 'html-loader', options: { minimize: false, // html不解决link\script标签(为了引入动态资源不hash) sources: { list: [ '...', { tag: 'script', attribute: 'src', type: 'src', filter : () => false, }, { tag: 'link', attribute: 'href', type: 'src', filter : () => false, } ] } } } ]}4、解决js、css进行兼容与压缩 ...

July 23, 2021 · 2 min · jiezi

关于webpack:webpack

mode: development\productionentryoutputdevtoolcontentBaseopenportproxyhotoptimizationtree shaking: 过滤导入没用的代码;production下默认关上package.json: sideEffectscode splitting 代码宰割 默认配置splitChunks: { chunks: 'async', minSize: 20000, minRemainingSize: 0, minChunks: 1, // 援用次数 maxAsyncRequests: 30, // 最大并行申请数 maxInitialRequests: 30, // 入口点最大并行申请数 enforceSizeThreshold: 50000, cacheGroups: { defaultVendors: { // 第三方包 test: /[\\/]node_modules[\\/]/, priority: -10, reuseExistingChunk: true, }, default: { // 业务代码 minChunks: 2, priority: -20, reuseExistingChunk: true, }, },}缓存: output:filename: [name].[contenthash].jsshimming懒加载 lazy loading:通过import动静引入,实现懒加载(webpackPrefetch、webpackPreload)打包剖析 webpack-bundle-analyzercss 代码宰割

July 23, 2021 · 1 min · jiezi

关于webpack:webpack配置打包优化

一、在根目录新建vue.config.js,设置动态资源门路为’./’,否则打包后我的项目无奈运行 module.exports = { publicPath: "./"}二、敞开生产环境下的SourceMap映射文件,包的大小缩小80% module.exports = { productionSourceMap: false,}三、进行跨域配置 module.exports = { devServer: { open: false, // 主动启动浏览器 host: '0.0.0.0', // localhost port: 6060, // 端口号 hotOnly: false, // 热更新 overlay: { // 当呈现编译器谬误或正告时,在浏览器中显示全屏覆盖层 warnings: false, errors: true }, proxy: { //配置跨域 '/api': { target: 'https://www.test.com', // 接口的域名 // ws: true, // 是否启用websockets changOrigin: true, // 开启代理,在本地创立一个虚构服务端 pathRewrite: { '^/api': '/' } } } }}四、配置 alias 别名 ...

July 22, 2021 · 2 min · jiezi

关于webpack:webpack-热更新

本节咱们学习 webpack 的模块热更新,也能够叫做模块热替换。其目标是为了放慢用户的开发速度,进步编程体验,不便开发人员在不刷新页面的状况下,就能批改代码,并且直观地在页面上看到变动。这个性能次要用于开发过程中,对于生产环境没有任何帮忙。 什么是模块热更新HMR 全称为 Hot Module Replacement ,中文意思为模块热更新,是 webpack 提供的最有用的性能之一。它容许在运行时替换,增加,删除各种模块,而无需进行齐全刷新从新加载整个页面。热更新中的“热”咱们能够了解为这个模块正在运行中,热替换就是将正在运行的模块进行替换。 热更新次要能够通过以下几种形式来显著放慢发速度: 保留在齐全从新加载页面时失落的应用程序的状态。只更新扭转的内容,以节俭开发工夫。调整款式更加疾速,简直等同于就在浏览器调试器中更改款式。启用热更新HMR 的启动其实很简略,须要应用到 webpack-dev-server 插件和 HMR 插件。 如果要通过 webpack-dev-server 启动 webpack 的开发环境,能够关上 webpack-dev-server 的热更新开关,例如上面是在 webpack.config.js 配置文件中的演示代码: module.exports = { devServer: { hot: true, // 关上热更新开关 }}在 webpack.config.js 中退出 HotModuleReplacementPlugin 插件,因为这个插件是 webpack 自带的,如果能够间接退出: module.exports = { plugins: [ webpack.HotModuleReplacementPlugin(), ]}热更新Less代码编译在理论利用中,咱们个别不会间接编写 CSS 代码,而是应用 CSS 预编译器,例如 Less、Sass、Stylus 来将写好的代码编译成 CSS 代码。咱们应用 Less 来举例,在 webpack 中如果咱们要应用 Less 代码编译成 CSS 代码,在打包时须要用到一个 less-loader 加载器。而要将 Less 代码正确编译成 CSS 代码则还须要用到 style-loader 和 css-loader 。 ...

July 20, 2021 · 1 min · jiezi

关于webpack:webpack-图片处理和优化

本节咱们来学习如何在 webpack 中解决和优化图片。后面咱们讲过,webpack 中只有 JS 类型文件才可能被辨认并间接打包,其余类型的文件,例如 CSS、JS、图片等,则须要通过特定的 loader 来进行加载打包。 而在理论我的项目中,咱们也会常常用到图片,所以本节咱们就来看一下如何在 webpack 中打包图片。 如何在webpack中打包图片在 webpack 中打包图片要用到 file-loader 或者 url-loader 加载器,这两个加载器的性能根本一样,然而还是存在一些区别: file-loader:可能依据配置项复制应用到的资源到构建之后的文件夹,并且可能更改对应的链接。url-loader :蕴含 file-loader 的全副性能,并且可能依据配置将合乎配置的文件转换成 Base64 形式引入,将小体积的图片 Base64 引入我的项目能够缩小 http 申请,也是一个前端罕用的优化形式。上面咱们应用 url-loader 为例,阐明一下在 webpack 中打包图片的办法。 示例:例如持续应用之前的 xkd_webpack 我的项目,在我的项目根目录下创立一个用于寄存图片的 images 文件夹。而后在这个文件夹上面任意增加一张图片,例如img1.png。 而后咱们在 xkd.css 中应用这张图片,代码如下所示: html{ background: url("./images/img1.png") no-repeat center;}而后咱们能够执行打包命令,然而此时会报一个谬误,如下图所示: 这个谬误通知咱们,须要应用一个 loader 来解决图片这种类型的文件。所以咱们须要装置 url-loader 加载器,并在配置文件中增加相干配置。 装置url-loader装置 url-loader 的命令很简略,如下所示: npm install url-loader --save-dev装置好后,咱们须要在 webpack.config.js 文件中的 module.rules 数组中增加 url-loader 的相干配置,例如上面这段配置代码: module:{ rules:[ { test: /\.(png|jpg|gif|svg)$/, use: 'url-loader' } ]}此时咱们再次执行打包命令,就能胜利进行打包啦。 ...

July 18, 2021 · 1 min · jiezi

关于webpack:转关于-tapable-你需要知道这些

在浏览 webpack 前如果不理解 tapable 的话,很有可能会看得云里雾里,那么 tapable 到底是什么,又有什么用呢?本文次要介绍 tapable 的应用以及相干实现,通过学习 tapable 可能进一步的理解 webpack 的插件机制。以下内容皆基于 tapable v1.1.3 版本。 tapable 是一个相似于 Node.js 中的 EventEmitter的库,但更专一于自定义事件的触发和解决。webpack 通过 tapable 将实现与流程解耦,所有具体实现通过插件的模式存在。 根本应用想要理解 tapable 的实现,那就必然得晓得 tapable 的用法以及有哪些应用姿态。tapable 中次要提供了同步与异步两种钩子。咱们先从简略的同步钩子开始说起。 同步钩子SyncHook以最简略的 SyncHook 为例: const { SyncHook } = require('tapable');const hook = new SyncHook(['name']);hook.tap('hello', (name) => { console.log(`hello ${name}`);});hook.tap('hello again', (name) => { console.log(`hello ${name}, again`);}); hook.call('ahonn');// hello ahonn// hello ahonn, again能够看到当咱们执行 hook.call('ahonn') 时会顺次执行后面 hook.tap(name, callback) 中的回调函数。通过 SyncHook 创立同步钩子,应用 tap 注册回调,再调用 call 来触发。这是 tapable 提供的多种钩子中比较简单的一种,通过 EventEmitter 也能轻松的实现这种成果。 ...

July 17, 2021 · 4 min · jiezi

关于webpack:webpack-如何压缩文件

本节咱们学习如何压缩 webpack 中的文件。在理论利用中,为了放大打包后包的体积,咱们可能须要将 CSS 和 JS 文件进行压缩,这须要用到 webpack 中的不同插件来实现。 压缩 CSS在 webpack 中要压缩 CSS 文件,须要用到 optimize-css-assets-webpack-plugin 插件,这个插件会在 webpack 构建过程中搜寻 CSS ,并优化 CSS。 首先咱们须要装置这个插件,命令如下所示: npm install optimize-css-assets-webpack-plugin --save-dev执行命令后,会发现插件胜利增加到了 package.json 文件中的 devDependencies 依赖中。 这个插件在应用时能够承受以下选项: assetNameRegExp:一个正则表达式,批示应优化的资产的名称。提供的正则表达式针对配置中ExtractTextPlugin 实例导出的文件的文件名运行,而不是源 CSS 文件的文件名。默认为 /\.css$/g。cssProcessor:用于优化 CSS 的 CSS 处理器,默认为 cssnano 。这应该是一个遵循 cssnano.process接口的函数(接管 CSS 和 options 参数并返回一个Promise)。cssProcessorOptions:传递给 cssProcessor 的选项,默认为 {}。canPrint:一个布尔值,批示插件是否能够将音讯打印到控制台,默认为 true。示例:而后咱们能够在 webpack.config.js 配置文件中配置这个插件,留神一下,咱们之前在学习插件的时候就讲到过,插件在应用之前须要先通过 require 援用。 const OptimizeCssAssetsPlugin = require('optimize-css-assets-webpack-plugin');module.exports = { entry: { entry:'./index.js', }, output: { path:__dirname + '/dist', filename:'./bundle.js' }, module:{ rules:[ { test:/.css$/, use:['style-loader','css-loader'] }] }, mode: 'production', plugins: [ new OptimizeCssAssetsPlugin({ assetNameRegExp: /\.optimize\.css$/g, cssProcessor: require('cssnano'), cssProcessorPluginOptions: { preset: ['default', { discardComments: { removeAll: true }, normalizeUnicode: false }], }, canPrint: true }) ]}压缩 JS如果咱们要在 webpack 中压缩 JS ,能够应用 uglifyjs-webpack-plugin 插件。uglifyjs-webpack-plugin 插件用来对 JS 文件进行压缩,减小 JS 文件的大小,减速加载速度。因为这个插件会拖慢 webpack 的编译速度,所以个别咱们在开发时会将其敞开,部署的时候再将其关上。 ...

July 16, 2021 · 1 min · jiezi

关于webpack:webpack-plugins插件

本节咱们来学习 webpack 中的插件(plugins),插件能够让 webpack 可能执行更多任务,从优化和压缩,到从新定义环境中的变量等,十分弱小。 在 webpack 中, Plugin 和 loader 是两个比拟容易混同的概念。loader 用于对模块的源代码进行转换,所以 loader 的执行层面是单个的源文件。而插件的目标在于解决 loader 无奈实现的问题,所以插件的性能更加弱小,插件的执行层面是整个构建过程。 上一节咱们在学习loader 时能够发现,在应用 loader 时是不须要援用的。而在应用插件时咱们必须先通过 require 援用该插件。 webpack 中有丰盛的内置插件和内部插件,并且容许用户自定义插件。 装置插件例如咱们通过在理论利用中常常会应用到的插件 html-webpack-plugin 来举例,讲一下插件的具体应用。html-webpack-plugin 插件能够用于主动生成根本的 HTML 页面。 首先咱们须要先装置 html-webpack-plugin 插件,命令如下所示: npm install html-webpack-plugin --save-dev装置好后,插件会主动增加到 package.json 文件中的依赖中,并指定了插件的版本,如下图: "devDependencies": { "css-loader": "^3.6.0", "html-webpack-plugin": "^4.3.0", "style-loader": "^1.2.1", "webpack": "^4.43.0", "webpack-dev-server": "^3.11.0"}配置插件插件装置好后,咱们在配置文件 webpack.config.js 中引入这个插件: const HtmlWebpackPlugin = require('html-webpack-plugin'); // 援用内部插件而后在配置中加上 plugins 节点,外面加上此插件实例,plugins 示意插件入口,所有插件都在这里配置。 const HtmlWebpackPlugin = require('html-webpack-plugin'); // 援用内部插件module.exports = { entry: { entry:'./index.js', }, output: { path:__dirname + '/dist', filename:'./bundle.js' }, module:{ rules:[ { test:/.css$/, use:['style-loader','css-loader'] }] }, mode: 'production', plugins: [ new HtmlWebpackPlugin() ]}配置好后,能够执行 npm run build 命令,此时会在 dist 目录下主动生成一个 index.html 文件。index.html 是默认的文件名称。 ...

July 13, 2021 · 1 min · jiezi

关于webpack:webpack-loader使用

本节咱们来学习 webpack 中 loader 加载器的应用,那么什么是 loader 呢。从实质上来说,loader 就是一个 Node.js 模块,在 webpack 的定义中,loader 导出一个函数,loader 会在转换源模块的时候调用该函数。 webpack 自身仍然是只能解决 JS 文件的,然而通过一系列的 loader ,就能够解决其余文件啦。例如 Less 和 Sass,以前咱们编译这些 CSS 预处理器,须要应用 gulp 进行编译,而显示能够通过 webpack 中的 loader 加载器来实现。 常见loaderwebpack 中有一系列的 loader,在理论我的项目中,咱们会依据不同的需要应用到不同的 loader。例如 webpack 中的一些常见 loader 如下所示: css-loader : 用于解决 css 文件,使得能在 js 文件中引入应用。style-loader : 用于将 css 文件注入到 index.html 中的 <style> 标签上。less-loader:解决 less 代码。sass-loader: 解决 sass 代码。postcss-loader:用 postcss 来解决 CSS代码。babel-loader:用 babel 来转换 ES6 文件到 ES5。file-loader:打包图片,打包字体图标。url-loader:和 file-loader 相似,然而当文件小于设定的 limit 时,能够返回一个 DataUrl(晋升网页性能)。html-withimg-loader:打包 HTML 文件中的图片。eslint-loader:用于查看常见的 JavaScript 代码谬误,也能够进行"代码标准"查看。loader的装置和配置咱们能够在 webpack.config.js 配置文件中配置 loader,能够在 module.rules 中指定一个或多个 loader。 ...

July 11, 2021 · 1 min · jiezi

关于webpack:使用-airpack-让你的-webpack-配置模块化

airpack 是一个 webpack-cli 的包装器。旨在让你更优雅的应用 webpack。 airpack 在 node 加载 webpack-cli 模块时,给 webpack-cli 打上性能加强补丁。这个补丁让 webpack-cli 能按肯定的优先级程序主动从多个地位(我的项目依赖、我的项目目录、命令行参数)读取 webpack 配置,而后用更适合的形式合并这些 webpack 配置。 应用 airpack 时,你的 package.json 看起来就像这样: { "scripts": { "dev": "NODE_ENV=development airpack --server", "build": "NODE_ENV=production airpack" }, "devDependencies": { "@arzyu/webpack-config-web": "^0.1.3", "airpack": "^1.0.1", "webpack-cli": "^4.7.2", "webpack-dev-server": "^3.11.2" },}npm run dev,启动本地开发服务(调用 webpack serve)npm run build,运行打包(调用 webpack)通过这种形式应用 webpack 配置会有很多益处: 我的项目目录会更洁净,只有我的项目相干的逻辑,没有 .babelrc.*、postcss.config.js、.eslintrc.*、…,甚至也不须要 webpack.config.*。我的项目模板化会更不便。能够参看范例我的项目:arzyu/react-webpack-playground。应用更少的 devDependencies,依赖列表的长度从一个胳膊缩短到了一根手指,所有与 webpack 配置相干的依赖都放在独立的 webpack-config-* 包中。应用独立的 webpack-config-* 包更容易治理,版本控制、迭代会更不便,同时也利于分享。将包公布到本人或组织的名下更适合,能够参考范例配置:@arzyu/webpack-config-web。简单的配置还能够拆分为多个包,airpack 能帮你合并它们。更具体的阐明,请移步我的项目仓库查阅:https://github.com/arzyu/airpack

July 9, 2021 · 1 min · jiezi

关于webpack:webpack-output出口

上一节咱们将了 webpack 的入口 entry,那既然有入口,对应就会有进口。所以本节咱们来讲 webpack 中的进口 output。 output 属性用于指定 webpack 如何输入、以及在哪里输入它所创立的 bundles,以及如何命名这些文件。基本上整个应用程序构造都会被编译到指定的输入门路的文件夹中。咱们能够通过在配置文件中指定一个 output 字段,来配置这些处理过程。 output输入配置output 是一个 object 对象,其中蕴含一系列的配置项,其中比拟重要的是 filename 和 path。 output.filename:配置输入文件的名称,指定一个 string 类型的值。如果只有一个输入文件,则能够把它写成动态不变的。output.path :配置输入文件寄存在本地的目录,是一个 string 类型的绝对路径。通常通过 Node.js 的 path 模块去获取绝对路径。在 webpack.config.js 配置文件中,一个 entry 对应一个 output。 示例:例如上面这段代码: module.exports = { entry:'./index.js', output:{ path:__dirname, filename:'./bundle.js' }}代码中通过 entry 属性为 webpack 指定了一个入口文件 index.js。通过 output 属性为 webpack 指定了一个进口文件,即 bundle.js。 当 webpack 有多个 entry 的时候,一个 entry 应该对应一个 output,此时输入的文件名须要应用替换符申明以确保文件名的唯一性。 示例:module.exports = { entry: { app: './one.js', search: './two.js' }, output: { path: __dirname + '/dist', filename: '[name].js', }}最终在我的项目根目录下的 dist 文件夹中生成 one.js 和two.js 两个 bundle 文件。 ...

July 8, 2021 · 1 min · jiezi

关于webpack:webpack-entry入口

上一节咱们讲到了 webpack 的配置文件 webpack.config.js ,这个文件须要咱们手动在我的项目根目录下创立。创立后要对其进行配置,本节咱们来看一下如何配置 webpack 中的入口,也就是 entry 属性。 entry 入口能够用于指定 webpack 是从哪个模块开始构建我的项目的,通过配置 entry 属性的值能够指定一个或多个入口终点,默认值为 ./src。 entry 的三种模式在 webpack.config.js 配置 entry 属性,有三种模式的值,其中 string 和 array 用于配置单个入口。object 用于配置多个入口。 string :字符串类型,入口模块的文件门路能够是相对路径。array :数组类型,能够将多个文件打包为一个文件。object :对象类型,每个入口生成一个 Chunk。单个入口配置如果要配置单个入口文件,能够给 entry 指定一个 string 或者 array 类型的值,这样就只会生成一个 chunk,当没有配置入口的文件对象名称时,默认应用 main 。 例如咱们如果要给 entry 属性传递一个字符串类型的值,能够像上面这样写: entry:'./path/file.js'另外,如果传入的是一个数组类型的值,则将会创立多个主入口,并将它们的依赖导向到一个chunk 中。例如上面代码示意当咱们执行命令后,a.js 和 b.js 会合并打包到 bundle.js 文件中: entry:['./path/a.js','./path/b.js'],示例:咱们能够通过一个具体的小例子来看一下 entry 的应用。上面是咱们须要的代码: // a.js文件function a(){ console.log("这是一个a.js文件");}// b.js文件function b(){ console.log("这是一个b.js文件");}而后配置 webpack.config.js 文件: module.exports = { entry:['./a.js','./b.js'], // 传入一个数组 output:{ path:__dirname, filename:'./bundle.js' }}接着执行 npm run build 命令,能够看到,a.js 和 b.js 文件同时被打包到 bundle.js 文件中啦,如下图所示: ...

July 6, 2021 · 1 min · jiezi

关于webpack:webpack-配置文件

像上一节中,咱们每次在打包文件时都须要手动输出源文件名和输入文件名,这样会比拟麻烦,要解决这个问题,咱们能够应用配置文件来进行治理。 本节咱们来学习 webpack 的配置文件 webpack.config.js ,因为 webpack 配置文件是导出一个对象的 JavaScript 文件,因而很少有 webpack 的配置看起来是完全相同的。 因为 webpack 配置是一个规范的 Node.js 模块,所以在配置文件中能够执行以下操作: 通过 require() 导入其余文件。通过 require() 应用 npm 的工具函数。应用 JavaScript 控制流表达式,例如 ?: 操作符。对罕用值应用常量或变量。编写和执行函数以生成配置的一部分。创立webpack.config.js配置文件webpack 在执行打包命令的时候,除了在命令行传入参数,例如 webpack 入口文件门路 输入文件门路 。还能够通过指定的配置文件来执行。默认状况下,会搜寻我的项目中的 webpack.config.js 文件,这个文件是一个 Node.js 模块,返回一个 json 格局的配置信息对象,或者通过 --config 选项来指定配置文件。 通常 webpack.config.js 文件放在我的项目的根目录下,例如咱们在 xkd_webpack 我的项目根目录下创立一个 webpack.config.js 文件,在这个文件中来配置解决入口文件和输入文件。 示例:module.exports = { entry:'./index.js', output:{ path:__dirname, filename:'./bundle.js' }, mode: 'development'}这样咱们只须要在命令行中执行 webpack 命令,就会开始主动打包文件啦。 执行 webpack 命令后,呈现如下图所示内容阐明文件打包胜利: 能够看到,执行 webpack 命令的运行后果和上一节的中 webpack index.js -o bundle.js 命令的运行执行后果是一样的,然而很显然,执行 webpack 命令要不便很多。 ...

July 4, 2021 · 1 min · jiezi

关于webpack:Webpack-原理系列八产物转译打包逻辑

全文 6000 字,咱们来聊聊打包闭环,欢送点赞关注转发。回顾一下,在之前的文章《有点难的 webpack 知识点:Dependency Graph 深度解析》曾经聊到,通过 构建(make)阶段 后,Webpack 解析出: module 内容module 与 module 之间的依赖关系图 而进入 生成(seal)阶段 后,Webpack 首先依据模块的依赖关系、模块个性、entry配置等计算出 Chunk Graph,确定最终产物的数量和内容,这部分原理在前文《有点难的知识点: Webpack Chunk 分包规定详解》中也有较具体的形容。 本文持续聊聊 Chunk Graph 前面之后,模块开始转译到模块合并打包的过程,大体流程如下: 为了不便了解,我将打包过程横向切分为三个阶段: 入口:指代从 Webpack 启动到调用 compilation.codeGeneration 之前的所有前置操作模块转译:遍历 modules 数组,实现所有模块的转译操作,并将后果存储到 compilation.codeGenerationResults 对象模块合并打包:在特定上下文框架下,组合业务模块、runtime 模块,合并打包成 bundle ,并调用 compilation.emitAsset 输入产物这里说的 业务模块 是指开发者所编写的我的项目代码;runtime 模块 是指 Webpack 剖析业务模块后,动静注入的用于撑持各项个性的运行时代码,在上一篇文章 Webpack 原理系列六: 彻底了解 Webpack 运行时 曾经有具体解说,这里不赘述。 能够看到,Webpack 先将 modules 逐个转译为模块产物 —— 模块转译,再将模块产物拼接成 bundle —— 模块合并打包,咱们上面会依照这个逻辑离开探讨这两个过程的原理。 一、模块转译原理1.1 简介先回顾一下 Webpack 产物: ...

July 2, 2021 · 6 min · jiezi

关于webpack:webpack-文件打包

上一节中,咱们曾经装置好了 webpack ,本节咱们来学习 何应用 webpack 进行文件打包。 应用webpack打包文件要打包文件,首先咱们须要初始化一个我的项目,后面咱们曾经创立好了一个 xkd_webpack 的我的项目,并且这个我的项目根目录下曾经有了一个 package.json 文件、package-lock.json 文件和一个 node_modules 文件夹,如下所示:在理论我的项目中,为了方便管理许多文件,咱们可能须要创立一个 src 文件夹寄存入口文件等开发文件,而后创立一个 dist 文件夹寄存最终打包的文件,还有其余类型的文件,为了方便管理咱们也会放在同一个目录下。 然而因为咱们这里只是举例说一下如何应用 webpack 打包文件,所以咱们间接我的项目根目录下,创立一个动态页面 index.html 和一个 JS 的入口文件 index.js 文件,文件名称是咱们自定义的,如果你想应用其余的名称也是能够的。 上面是 index.html 文件的内容: <html> <head> <meta charset="utf-8"> <title>webpack入门</title> </head> <body> <script type="text/javascript" src="bundle.js"></script> </body></html>在这个 HTML 文件中咱们引入了一个 bundle.js 文件,这个 bundle.js 文件就是最终的打包后的文件,然而当初还没有生成哟,要等咱们执行完打包命令后才会生成这个文件。 而后入口文件 index.js 的内容如下所示: document.write('你好,侠课岛!');最初执行下列命令,就能够胜利将 index.js 文件打包到 bundle.js文件中: webpack index.js -o bundle.js执行命令成果如下所示: 命令执行胜利后,我的项目根目录下会生成一个 bundle.js 文件。这个文件的作用就是用了一个立刻执行函数,而后将 index.js 的内容封装成一个函数,作为参数传进外部执行,这样就实现了文件的打包: 此时咱们在浏览器中关上 index.html 文件,页面将会显示 "你好,侠课岛!",这同时也能证实 index.js 文件胜利打包到了 bundle.js 文件中,因为咱们只在 index.html 文件中引入了 bundle.js 文件。 ...

July 1, 2021 · 1 min · jiezi

关于webpack:webpack-学习1

webpack官网:https://webpack.docschina.org...为什么应用webpack?回顾一下历史,之前是如何开发我的项目的第一阶段(1)在每个html文件中都援用大量的<script>标签这种形式会造成网络瓶颈,并且加载大量的无用代码(2)只引入一个js文件,这个js里蕴含了整个我的项目的所有代码,几万行甚至几十万行代码。这种形式会导致作用域不好辨别,同时难以保护第二阶段IIFE立刻执行函数(function(){})()解决大型项目的作用域问题,Grunt、Gulp就是应用这种模式。当然这样做也有一些问题,比方批改了一个文件也要从新构建整个我的项目。引入第三方库时,即便只须要大量代码,也要引入整个第三方库代码,不能做到代码宰割。第三阶段应用webpack(实质上,webpack只是动态模块打包工具)当然,webpack是基于以下的根底条件或者启发之后产生的(1)node.js的诞生,让js能够在浏览器之外的计算器和服务中运行(2)common.js引入了require机制,容许在以后文件中加载其余模块(浏览器不反对common.js的模块机制,因而呈现了Browserify, RequireJS 和 SystemJS 等打包工具,容许咱们编写可能在浏览器中运行的common.js模块)

July 1, 2021 · 1 min · jiezi

关于webpack:hashchunkhash以及contenthash的区别

hash我的项目级别的hash,只有我的项目中任意文件扭转就会产生扭转 chunkhash每个entry对应不同的chunk只有入口文件或者入口文件引入的文件(及引入文件引入的文件等)产生扭转,chunkhash都会产生扭转。就是说chunk内的任何文件扭转,chunkhash都会扭转 contenthashcontenthash示意由文件内容产生的hash值,内容不同产生的contenthash值也不一样。举个例子,如果css文件没有抽出去,那么扭转css文件,打包后生成js文件的内容就产生了扭转,那么js的contenthash就变了。如果css曾经通过mini-css-extract-plugin抽出打包了。那么css扭转,并不会影响生成的js文件内容,所以js的contenthash不会扭转

June 29, 2021 · 1 min · jiezi

关于webpack:Webpack-安装

本节咱们来学习 webpack4.0 的装置,webpack 的运行须要依赖 Node.js 的运行环境,在装置 webpack 时也须要用到 npm ,所以咱们须要先装置 Node.js,Node.js 自带了软件包管理器 npm。 webpack 须要 Node.js v0.6 以上版本反对,所以倡议应用最新版,装置地址为:https://nodejs.org/en/download/,装置过程如果不相熟的同学能够去看一下 Node.js 入门教程,这里就不给大家演示啦。 创立一个我的项目首先咱们须要创立一个我的项目文件,例如在桌面上创立一个 xkd_webpack,而后在终端中进入这个我的项目的根目录,如下图:而后能够执行 npm init 命令初始化我的项目,这时会在我的项目根目录下主动生成一个 package.json 文件,这个文件中是一些配置信息:在初始化时会显示一些问题,如果这些问题咱们全副抉择默认答案,则能够间接执行 npm init --yes 来间接创立 package.json 文件。 上面是一个创立好的 package.json 文件内容: { "name": "xkd_webpack", "version": "1.0.0", "description": "", "main": "index.js", "scripts": { "test": "echo \"Error: no test specified\" && exit 1" }, "author": "", "license": "ISC", "devDependencies": { }}初始化结束之后就能够开始装置 webpack,有两种装置 webpack 的形式,一种是全局装置,一种是部分装置。 package.json字段咱们来看一下 package.json 文件中的字段,name 和 version 字段是 package.json 文件中的必须字段,一起组成惟一的标识符。 ...

June 29, 2021 · 1 min · jiezi

关于webpack:webpack-简介

本教程咱们来学一下 webpack 的根底入门常识,webpack 作为一个 JavaScript 应用程序的动态模块打包器,能够将各种动态资源作为模块来解决,是当下前端工程化的一个很受欢迎的工具,咱们将在 webpack4.0 的根底上来学习 webpack 的应用。 什么是webpackwebpack 是一个开源的前端打包工具,webpack 提供了前端开发不足的模块化开发方式,将各种动态资源视为模块,并从它生成优化过的代码,例如动态资源能够包含 js、css、html、less、图片等等。 webpack 能够从终端或者是通过更改 webpack.config.js 文件来设置各项性能。咱们要应用 webpack,有一个前提条件就是必须先装置 Node.js, 在装置 webpack 或者其余的插件等都须要用到 npm 命令。 webpack 其中一个个性是应用加载器来将资源转化成模块,开发者能够自定义加载器的程序、格局来适应我的项目的需要。 为什么应用webpack咱们在开发的时候,常常会遇到在一个 HTML 页面中引入多个 CSS 和 JS 文件,或者是一些 JS 资源彼此之间存在依赖关系,或者是须要应用一大堆安装包的状况,这些问题可能容易导致页面加载迟缓。所以为了解决这个问题,咱们能够应用 webpack 来打包这些文件,将各种动态资源都打包成了一个文件,这样浏览器加载起来就快很多。 在 webpack 中,任何动态资源都能够视为模块,模块之间也能够相互依赖,通过 webpack 对模块进行解决后,能够打包成咱们想要的动态资源。 webpack四个外围概念webpack 中有四个外围概念,包含入口(entry)、输入(output)、loader、插件(plugins)。如下所示: entry:用于指定 webpack 应该应用哪个模块来作为构建的开始,能够指定一个或多个终点,默认值为 ./src。output:指定 webpack 最终输入的文件输入地位和文件名等信息,默认输入地位为 ./dist。loader:能够将所有类型的文件转换为 webpack 可能解决的无效模块,而后咱们就能够利用 webpack 的打包能力,对它们进行解决。plugins:目标在于解决 loader 无奈实现的其余事。能够让 webpack 可能执行更多任务,从优化和压缩,到从新定义环境中的变量,性能十分弱小。webpack劣势webpack 是以 commonJS 的模式来书写脚本的,但对 AMD/CMD 的反对也很全面,不便旧我的项目进行代码迁徙。能够通过配置,打包成多个文件,无效利用浏览器的缓存性能晋升性能。将款式文件和图片等动态资源也可视为模块进行打包。配合 loader 加载器,能够反对 Sass,Less 等 CSS 预处理器。专一于解决模块化的我的项目,能做到开箱即用、 一步到位。扩展性强,插件 plugins 机制欠缺。总结webpack 是一个模块打包工具,或者也能够叫做模块化打包机。通过 webpack 能够帮忙咱们将不同的资源和文件,进行打包,也就是合并在一个文件外面。除此之外,webpack 还能够进行 CSS 预处理,将 ES6 转为 ES5 等作用。下一节咱们将会学习如何装置 webpack 。 ...

June 27, 2021 · 1 min · jiezi

关于webpack:Tapable个人笔记

webpack 底层外围是一个独立的工具库tapable webpack编译过程,能够看作 事件驱动型事件工作机制 外围的两个: 负责编译的complier,负责创立bundles的compilation都是tapable的实例对象 配置初始化内容编译输入编译后内容tapable工作流程 实例化hook注册事件监听通过hook触发事件监听执行懒编译生成的可执行代码hook自身是实例对象,在tapable库中存在几种不同类,每个类实例都是一种hook实例(钩子),不同钩子领有不同执行特点,从执行机制将hook分为同步和异步,异步分为并行串行两种模式 Hook不同机制执行特点 Hook:一般钩子,监听器之间相互独立不烦扰BailHook:熔断钩子,某个监听返回非undefined时后续不执行WaterfallHook:瀑布钩子,上一个监听的返回值可传递至下一个LoopHook:循环钩子,如果以后未返回false则始终执行总结: tapable是个库,外部提供不同类,能够实例化出不同hookhook分为同步异步两类,无论哪类都蕴含下面四个执行特点tapable库同步钩子 SyncHookSyncBailHookSyncWaterfallHookSyncLoopHooktapable库异步串行钩子 AsyncSeriesHookAsyncSeriesBailHookAsyncSeriesWaterfallHooktapable库异步并行钩子 AsyncParallelHookAsyncParallelBailHook同步钩子应用装置:yarn add tapable --dev应用:导入->实例化->增加监听->触发监听 测试SyncHook// 导入const { SyncHook } = require('tapable')// 实例化let hook = new SyncHook(['name','age'])// 增加事件监听hook.tap('fn1',function(name,age){ // 钩子监听触发时会执行此函数体 console.log("SyncHook:fn1-->",name,age);})// 触发监听函数hook.call('mcgee',18)流式监听,能够定义多个监听事件顺次解决内容 const { SyncHook } = require('tapable')let hook = new SyncHook(['name','age'])// 增加事件监听hook.tap('fn1',function(name,age){ console.log("SyncHook:fn1-->",name,age); // SyncHook:fn1--> mcgee 18})hook.tap('fn2',function(name,age){ console.log("SyncHook:fn2-->",name+"爸爸",age+30); // SyncHook:fn2--> mcgee爸爸 48})hook.call('mcgee',18)测试SyncBailHook留神fn1return了非undefined的值,因而fn2不会执行,熔断的含意 const { SyncBailHook } = require('tapable')let hook = new SyncBailHook(['name','age'])hook.tap('fn1',function(name,age){ console.log("SyncBailHook:fn1-->",name,age); return 1; })hook.tap('fn2',function(name,age){ console.log("SyncBailHook:fn2-->",name+"爸爸",age+30);})hook.call('mcgee',18)测试SyncWaterfallHook返回值会被下一个监听获取 ...

June 25, 2021 · 3 min · jiezi

关于webpack:webpack打包是怎么执行的

webpack和webpack-cli是npm包,运行于node环境,执行打包操作时会执行: window环境下,执行yarn webpack理论查找了 node_modules/.bin/webpack.cmd 文件并执行webpack.cmd 内依据装置的cli(两种webpack-cli,webpack-command),实现不同解决逻辑。咱们装置了webpack-cli,因而依据代码 require 了 node_modules/webpack-cli/package.json 中的 bin 入口文件,也就是 ./bin/cli.jscli.js 是个 cli 执行命令行, 外部是 IIFE 函数 函数次要作用解决用户交互信息,require("webpack")并调用了 webpack(options)实例化 Compiler.js类,赋给 compiler变量,compiler继承 tapable 库,贯通整个编译流程(个别运行文件Compile.js都存在/lib目录下)给 compiler 设置 Node 文件读写能力给 compiler 循环挂载 咱们自定义的 plugins解决 webpack外部默认插件,其中最重要的是入口插件 EntryOptionPlugin, 此实例对象次要作用是 埋下一个 make 钩子监听给 make钩子 回调外部增加 compilation.addEntry 办法,此时钩子回调并未触发,addEntry也不会执行, 重要!条件解决实现,钩子也埋完后。调用 实例对象 run 办法,即 compiler.run,重要! run办法外部执行 compile 编译办法,compile 办法会 依据 compiler实例 创立一个 compilation 实例,compilation 继承自 tapable库实例化后,触发下面埋的 make 钩子,执行下面埋的 make 钩子的回调,并传入初始化的 compilation 实例对象此时执行 compilation.addEntry, 执行模块编译和打包生成dist的操作都在这个办法内, 重要!addEntry 内会 以 normalModuleFactory 模板创立一个 NormalModule 规范模块normalModuleFactory 类模板中有一些操作, (build办法, dobuild办法, 读取内容办法),用于操作编译咱们写的模块此时一个 规范的 NormalModule模块被创立,执行buildMoudle,操作 NormalModule 模块次要操作就是 读取文件内容,操作 ast 语法树批改文件内容(例如:require改成__webpack_require__,以及外部的文件援用门路)将批改后的内容写回到文件中,执行回调,也就是 afterBuild 办法在afterBuild中咱们会判断以后批改的模块是否有依赖,递归判断,将模块的依赖项也进行上述批改将模块和模块依赖批改后,执行回调,解决chunk问题,模块和模块依赖之间有chunk的关系,同一chunk能够有多个模块,以后所有的入口模块都被寄存在了 compilation 对象的 entries 数组里所谓封装 chunk 指的就是根据某个入口,而后找到它的所有依赖,将它们的源代码放在一起,之后再做合并跟谁合并?跟ejs模板文件合并,生成 dist/bundle.js 文件

June 25, 2021 · 1 min · jiezi

关于webpack:webpack打包后的文件分析

打包后的bundle.js源码剖析ctrl+k ctrl+0 缩进 打包后的函数是个函数自调用。以后函数调用时传入一个对象这个对象为了不便称之为模块定义,是个键值对对象键是入口文件门路拼接对象键值是个函数,相似于commonjs模块加载,包裹模块被加载的内容这个函数在未来某工夫下会被调用,函数能够接管参数,利用参数能够实现模块的加载将对象实参传给modules形参# bundle.js(function(modules){ ... // 缓存被加载过的模块 var installedModules = {}; // 外围函数,webpack中自定义的.作用是返回传入的模块的导出内容module.exports // 这个moduleId是iife传入参数对象的key function __webpack_require__(moduleId){ if(installedModules[moduleId]) { return installedModules[moduleId].exports; } var module = installedModules[moduleId] = { i: moduleId, l: false, exports: {} }; // 模块内的this指向 module.exports modules[moduleId].call(module.exports, module, module.exports, __webpack_require__); module.l = true; return module.exports } ... return __webpack_require__(__webpack_require__.s = "./src/index.js");})({ "./src/index.js": (function(module, exports) { console.log("index.js content"); })})一些属性办法 // 将模块定义保留一份,通过m属性挂载到自定义办法上__webpack_require__.m = modules// 挂载缓存的__webpack_require__.c = installedModules// 判断被传入的对象object 是否具备指定的属性,有返回true__webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); };// 给对象人为增加属性,内部能够通过getter拜访这个属性__webpack_require__.d = function(exports, name, getter) { if(!__webpack_require__.o(exports, name)) { Object.defineProperty(exports, name, { enumerable: true, get: getter }); }};// 给 exports 强行加标记__webpack_require__.r = function(exports) { //如果成立阐明是个 ESModule if(typeof Symbol !== 'undefined' && Symbol.toStringTag) { // 向对象exports增加一个惟一字符串Symbol.toStringTag标记,值人为定义成Module // Object.prototype.toString.call(exports) === Module Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' }); } // 向对象exports上增加一个__esModule属性,值是true Object.defineProperty(exports, '__esModule', { value: true })};// 提供一个getter办法,返回一个getter办法,如果是ESM返回默认值,否则返回模块__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;};// webpack.config中的publicPath,根目录,默认"/"// index.html不主动生成时,找不到index内引入的内容,增加'dist/'__webpack_require__.p = ""// 标记入口文件__webpack_require__.s = "./src/index.js"// 调用t时,咱们会拿到被加载模块得内容value// 对于value可能间接返回,或者解决之后返回// 接管两个参数,一个value示意模块id,第二个值 mode 是一个十进制数// &1 位运算获取 模块id的返回值// 8,4,ns,2是对模块返回值进行的额定解决,而后返回应用// 1,8成立相当于加载了CJS标准间接返回value// 1,4成立相当于加载了ESM间接返回value// 如果上述都不成立,持续解决value,将其挂载到ns的default属性上// 如果value是非根本类型,例如{name:xx,age:10},则能够通过ns.name,ns.age触发getter办法获取__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;};备注:t办法中的 bind() 办法创立一个新的函数,在 bind() 被调用时,这个新函数的 this 被指定为 bind() 的第一个参数,而其余参数将作为新函数的参数,供调用时应用。 ...

June 25, 2021 · 2 min · jiezi

关于webpack:敲黑板手把手带你写一个简易版webpack内附超详细分解

明确webpack实现的性能实质上,webpack 是一个古代 JavaScript 应用程序的动态模块打包器(module bundler)。 当 webpack 解决应用程序时,它会递归地构建一个依赖关系图(dependency graph),其中蕴含应用程序须要的每个模块,而后将所有这些模块打包成一个或多个 bundle。咱们的代码次要实现以下四步 graph TD A(1.找到入口文件) --> B(2.解析入口文件并提取出依赖) B --> C{3.递归发明出依赖图} C --> D(4.把所有文件打包成一个文件)开始开发 1.目录下新建三个js源文件 entry.jsimport message from './message.js'console.log(message)message.jsimport name from "./name.js"export default `${name} is a girl`name.jsexport const name = 'Yolanda'梳理下依赖关系,咱们的入口文件是entry.js,entry依赖message,message依赖name。 2.新建一个mywebpack.js文件,首先读取一下entry入口文件中的内容。读取文件须要用到node的一个根底api-fs(文件系统),fs.readFileSync能够同步拿到js文件中的代码内容。 mywebpack.jsconst fs = require('fs')function creatAsset (filename){ const content = fs.readFileSync(filename,'utf-8') console.log(content)}creatAsset('./source/entry.js')在当前目录下运行一下命令, 看一下输入node mywebpack.js 输入内容为entry.js中的代码: import message from './message.js';console.log(message); 3. 剖析ast,思考如何解析出entry.js文件中的依赖能够应用ast工具 https://astexplorer.net/看一下entry.js文件的ast是什么? 3.1 能够看到最下级是一个File, File中蕴含换一个program, 就是咱们的程序3.2 在program的body属性里, 就是咱们各种语法的形容3.3 能够看到第一个就是 ImportDeclaration, 也就是引入的申明. 3.4 ImportDeclaration里有一个source属性, 它的value就是引入的文件地址 './message.js' ...

June 24, 2021 · 4 min · jiezi

关于webpack:手动快速搭建webpack

vue-cli2中次要是用到webpack的两个外围性能是模块化、打包。比方在每个js文件中,同时定义一个变量 var x = "hello",在调用文件中批改这个变量,两个文件的变量x都被扭转了,造成了全局净化,这只是一个简略的例子;其实模块化,咱们本人不必webpack也是能够解决的,比方每个js文件用自执行函数来包起来,造成一个独立的作用域。然而这样很麻烦、也不好保护和扩大;以下手动搭建webpack根底我的项目的步骤:(如有谬误,评论区留言纠正,摘于本人的笔记,可能比拟糙) 1、首先,webpack是依赖于node,所以必须要装置node, node里蕴含npm,当然也能够yarn,其实当初yarn和npm的性能差不多; 输出指令 node -v 查看是否装置node,2、全局装置webpack, 输出指令进行全局装置 npm i -g webpack@3.6.0 ,只有是终端输出命令就是调用全局的webpack (vue-cli2就是用webpack@3.6.0), 同样通过指令 webpcak -v查看装置版本。装置实现后,就能够进行打包了,通过指令: webpack ./src/main.js(打包文件) ./dist/bundle.js(输入文件)。// .main.js是须要打包文件 bundle.js是输入文件webpack在打包的时候,会在main.js文件中,找到文件中引入的依赖,没有调用的依赖,不进行打包。3、其实能够通过创立webpack.config.js文件,来指定须要打包的文件和输入的文件; const path = require("path"); module.exports = { // entry: "./main.js", //入口 entry: { app: "./main.js" //这样配置就打包成app.js } output: { //输入 filename: "bundle.js", path: path.resolve(__dirname, "./dist") //绝对路径 } }4、步骤3用到path, 所以须要执行命令 npm init 进行初始化, 并且会多产生一个package.json文件和node_modules文件夹,先不论,前面会用到它; 5、在进行装置loader或者plugin之前, 须要装置在本地装置一下webpack,命令: npm i -D webpack@3.6.0 起因-> 1、如果这个时候须要通过webpack来进行打包的话,实现1234步骤后,按理只须要输出webpack进行打包就能够,然而在终端输出的指令都是调用全局装置的webpack; 2、可能本地webpack和全局的版本不一样,如果本地插件版本是依赖webpack@3.6.0, 而全局webpack的版本是@4.1.0 的话,到时候打包可能就存在loader和plugin版本不兼容的问题;6、接下来就是装置loader, 用来加载和解析各种格局的文件,装置loader有两个步骤: ...

June 23, 2021 · 2 min · jiezi

关于webpack:webpack配置

const path=require('path')var basePath = __dirname;var HtmlWebpackPlugin = require("html-webpack-plugin");//引入第三方库module.exports={ context: path.join(basePath, "src"),//根本目录,一个绝对路径,用于解析配置中的入口点和加载程序。 entry:[//入口 "./index.tsx" ], output:{//进口 path: path.join(basePath, "dist"), filename:"bundle.js" }, resolve: {//解析 extensions: [".js", ".ts", ".tsx"] }, module:{ rules: [ { test: /\.(js|tsx?)$/, exclude: /node_modules/, use: { loader: "awesome-typescript-loader",//TS转成指定版本的TS options: { useBabel: true, babelCore: "@babel/core", } } }, { test: /\.css$/, use: ["css-loader"] // use: ["style-loader","css-loader?sourceMap"] }, { test: /\.(png|jpg|gif|svg)$/, loader: "file-loader", options: { name: "assets/img/[name].[ext]?[hash]" } } ] }, devServer: { contentBase: "./dist", // Content base inline: true, // Enable watch and live reload host: "localhost", port: 8080, stats: "errors-only" }, plugins: [//插件 //Generate index.html in /dist => https://github.com/ampedandwired/html-webpack-plugin new HtmlWebpackPlugin({ filename: "index.html", //Name of file in ./dist/ template: "index.html", //Name of template in ./src hash: true })] }

June 19, 2021 · 1 min · jiezi

关于webpack:Webpack-简介

构建其实是工程化、自动化思维在前端开发中的体现,把一系列流程用代码去实现,让代码自动化地执行这一系列简单的流程。 构建给前端开发注入了更大的生机,解放了咱们的生产力。Webpack 凭借弱小的性能与良好的应用体验,曾经成为目前最风行,社区最沉闷的构建工具,是古代 Web 开发必须把握的技能之一。 背景在当下的前端环境里,各种框架和工具层出不穷,比方 React、Vue、Angular 等,极大的进步了咱们的开发效率,然而,他们都有一个共同点:源代码无奈间接运行,必须通过转换之后才可执行。 而转换代码的这个过程咱们能够称之为构建,被用来进行构建的工具咱们叫做构建工具,而 Webpack 便是其中的佼佼者。 构建工具的惯例作用: 代码转换:TypeScript 编译成 JavaScript、SCSS 编译成 CSS 等。文件优化:压缩 JavaScript、CSS、HTML 代码,压缩合并图片等。代码宰割:提取多个页面的公共代码、提取首屏不须要执行局部的代码让其异步加载。模块合并:在采纳模块化的我的项目里会有很多个模块和文件,须要构建性能把模块分类合并成一个文件。主动刷新:监听本地源代码的变动,主动从新构建、刷新浏览器。代码校验:在代码被提交到仓库前须要校验代码是否符合规范,以及单元测试是否通过。主动公布:更新完代码后,主动构建出线上公布代码并传输给公布零碎。Webpack 的概念Webpack 是应用 NodeJs 开发进去的一个构建工具,实质上,它是一个古代 JavaScript 应用程序的动态模块打包器(module bundler)。 当 Webpack 解决应用程序时,它会递归地构建一个依赖关系图(dependency graph),其中蕴含应用程序须要的每个模块,而后将所有这些模块打包成一个或多个 bundle。 在 Webpack 里所有文件皆模块,通过 Loader 转换文件,通过 Plugin 注入钩子,最初输入由多个模块组合成的文件。 Webpack 专一于构建模块化我的项目。借用 Webpack 官网首页的图片来看一下它到底是什么: 所有文件:JavaScript、CSS、SCSS、图片、模板,在 Webpack 眼中都是一个个模块,这样的益处是能清晰地形容出各个模块之间的依赖关系,以不便 Webpack 对模块进行组合和打包。 通过 Webpack 的解决,最终会输入浏览器能应用的动态资源。Webpack 的根本配置以下是 Webpack 的根本配置,次要蕴含了 webpack 的四个外围概念: 入口(entry)输入(output)loader插件(plugins)const path = require('path');module.exports = { // 模式配置 mode: "production", // "production" | "development" | "none" // 入口文件 entry: "./app/entry", // string | object | array output: { // webpack 如何输入后果的相干选项 path: path.resolve(__dirname, "dist"), // string }, module: { // 对于模块配置 rules: [ // 模块规定(配置 loader、解析器等选项) { test: /\.jsx?$/, } ] }, // 插件 plugins: [ // ... ],}Webpack 的优缺点长处: ...

June 11, 2021 · 1 min · jiezi

关于webpack:webpack编译速度优化

我的项目过大,编译就会十分慢,每次动手新我的项目看着爬一样的速度,切实忍不住会想优化一下编译速度 用speed-measure-webpack-plugin和webpack-bundle-analyzer 剖析我的项目 优化计划缓存优化 hard-source-webpack-plugin,这插件为模块提供两头缓存步骤,但我的项目得跑两次,第一次构建工夫失常,第二次大略能省去90%左右的工夫。npm i hard-source-webpack-plugin -D plugins: [ new HardSourceWebpackPlugin()]然而我的项目中其实没有独立的webpack.config.js文件,所以只能放在vue.config.js文件中,应用chainWebpack来将配置插入到webpack中去官网中的应用cache缓存 chainWebpack: (config) => { config.cache(true)}配合HardSourceWebpackPlugin chainWebpack: (config) => { config.plugin('cache').use(HardSourceWebpackPlugin)}

June 10, 2021 · 1 min · jiezi

关于webpack:Webpack-系列第六篇如何编写loader

全文 5000 字,深度分析 Webpack Loader 的个性、运行机制、开发技巧,欢送点赞关注。写作不易,未经作者批准,禁止任何模式转载!!!对于 Webpack Loader,网上曾经有很多很多的材料,很难讲出花来,然而要写 Webpack 的系列博文又没方法绕开这一点,所以我浏览了超过 20 个开源我的项目,尽量全面地总结了一些编写 Loader 时须要理解的常识和技巧。蕴含: 那么,咱们开始吧。 意识 Loader如果要做总结的话,我认为 Loader 是一个带有副作用的内容转译器!Webpack Loader 最外围的只能是实现内容转换器 —— 将各式各样的资源转化为规范 JavaScript 内容格局,例如: css-loader 将 css 转换为 __WEBPACK_DEFAULT_EXPORT__ = ".a{ xxx }" 格局html-loader 将 html 转换为 __WEBPACK_DEFAULT_EXPORT__ = "<!DOCTYPE xxx" 格局vue-loader 更简单一些,会将 .vue 文件转化为多个 JavaScript 函数,别离对应 template、js、css、custom block那么为什么须要做这种转换呢?实质上是因为 Webpack 只意识合乎 JavaScript 标准的文本(Webpack 5之后减少了其它 parser):在构建(make)阶段,解析模块内容时会调用 acorn 将文本转换为 AST 对象,进而剖析代码构造,剖析模块依赖;这一套逻辑对图片、json、Vue SFC等场景就不 work 了,就须要 Loader 染指将资源转化成 Webpack 能够了解的内容状态。 Plugin 是 Webpack 另一套扩大机制,性能更强,可能在各个对象的钩子中插入特化解决逻辑,它能够笼罩 Webpack 全生命流程,能力、灵活性、复杂度都会比 Loader 强很多。Loader 根底代码层面,Loader 通常是一个函数,构造如下: ...

June 9, 2021 · 7 min · jiezi

关于webpack:模块打包工具

模块打包工具ESM 存在环境兼容问题模块文件过多,网络申请频繁所有前端资源都须要模块化,不仅js文件毋庸置疑前端模块打包工具是必要的支流工具 Webpack Parcel Rollup WebPackwebpack入口 Rollup长处 输入后果更加扁平主动移除未援用代码打包后果仍然齐全可读毛病 加载非 ESM 的第三方模块比较复杂模块最终被打包到一个函数中,无奈实现 HMR浏览器环境中,代码拆分性能依赖 AMD 库如果咱们正在开发应用程序,须要大量引入第三方模块,利用过大还要分包 如果咱们开发一个框架或者类库,很少依赖第三方模块,大多数出名框架/库都在应用Rollup作为模块打包 总结:Webpack大而全,Rollup小而美,应用程序用webpack,库/框架Rollup Rollup入口 ParcelParcel公布于2017年,过后Webpack应用上过于繁琐,齐全零配置,构建速度快 vs.Webpack Webpack生态更好,扩大更丰盛Webpack越来越好用Parcel入口

June 5, 2021 · 1 min · jiezi

关于webpack:webpack笔记

Webpack性能包含 模块打包器(Module bundler)模块加载器(Loader)代码拆分(Code Splitting)模块增量加载,渐进式加载资源模块(Asset Module)打包工具解决的是前端整体的模块化,并不是单指JavaScript模块化 装置,因为是基于npm的包,所以 yarn init --yesyarn add webpack webpack-cli --dev (^4.40.2, ^3.3.9)yarn webpack --version 查看版本yarn webpack 开始打包,webpack主动从src/index.js开始打包4.0当前webpack执行反对零配置打包,将src/index.js作为打包入口 -> dist/main.js生成地址 增加配置文件 webpack.config.js,运行在node环境的js文件,按CommonJs形式编写代码 # webpack.config.jsconst path = require('path')module.exports = { entry:'./src/main.js', //我的项目打包入口文件门路 output:{ //输入文件配置,是个对象 filename:'bundle.js', //输入文件名称 path:path.join(__dirname,'output') //输入文件所在目录,必须是absolute path! }, mode:'development' //webpack4以上 工作模式(不同环境的几组预设配置) //默认是production,主动启动优化,优化打包后果 //development 优化打包速度,增加一些调试过程须要的辅助 //none 原始打包不会进行额定解决 // 应用yarn webpack --mode development执行}资源打包非js代码通过loader加载,Webpack外部的loader默认只能解决js,json文件 yarn add css-loader --dev (^3.2.0) yarn add style-loader --dev (^1.0.0) const path = require('path')module.exports = { entry:'./src/main.css', //我的项目打包入口文件门路 output:{ //输入文件配置,是个对象 filename:'bundle.js', //输入文件名称 path:path.join(__dirname,'dist') //输入文件所在目录,必须是absolute path! }, mode:'none',//production,development module: { rules:[ //除js外其余资源模块加载规定配置 { test:/.css$/, use:['style-loader','css-loader'] //匹配到的文件应用的loader } ] }}loader内的rules,use从后向前执行,通过style标签挂载到html上 ...

June 5, 2021 · 4 min · jiezi

关于webpack:手把手带你搭建一个简单的webpack脚手架一

这篇文章次要是从零开始,搭建一个基于webpack的反对react + less + ts的脚手架。次要是面向入门,心愿将整个搭建思路讲清楚来,帮忙老手搭建一个简略的webpack脚手架。曾经有相应教训的并不适宜。后续会退出单元测试,webpack优化等内容,也作为集体学习的总结。本文的github地址。欢送star,或是在issues提出相应的意见。git上相应的commit也记录了整个搭建过程与正文。能够间接看commit学习。注:本文webpack版本为5以上 webpack是什么?简而言之,webpack是对于古代js应用程序的动态模块打包器。官网上的图片也扼要的阐明了相应的关系。在我的项目中,因为各类文件资源相互依赖(比方html引入了image、字体资源等等)。webpack能够通过剖析文件之间的依赖构建的依赖图,而后递归的通过依赖图将多种资源整合构建成最初的动态资源。但具体原理并不是本文的深刻点,这里大略有一个印象为主,让咱们接着下一步。 初始化我的项目首先咱们须要创立一个我的项目,初始化npm,并在本地装置webpack和webpack-cli。(上面是在终端执行的命令行)。 mkdir webpack-democd webpack-demonpm init -ynpm install webpack webpack-cli --save-dev当初,咱们在根目录下创立以下目录文件和相应的内容。我的项目目录: webpack-demo |- package.json+ |- index.html+ |- /src+ |- index.jssrc/index.js function component() { const element = document.createElement('div'); // Lodash, currently included via a script, is required for this line to work element.innerHTML = _.join(['Hello', 'webpack'], ' '); return element;}document.body.appendChild(component());index.html <!DOCTYPE html><html> <head> <meta charset="utf-8" /> <title>Getting Started</title> <script src="https://unpkg.com/lodash@4.17.20"></script> </head> <body> <script src="./src/index.js"></script> </body></html>这是最原始的应用lodash库的形式,这时咱们将index.html在浏览器中运行能够看到hello webpack显示在页面上,这是因为index.html通过script标签引入了lodash库。所以index.js中的_.join能力执行将['Hello', 'webpack']拼成了'Hello webpack'。然而会带来几个问题: ...

June 1, 2021 · 4 min · jiezi

关于webpack:htmlwebpackplugin打包报错

打包报错TypeError: Cannot read property 'tap' of undefined at HtmlWebpackPlugin.apply (D:\MyData\xiamy9\study\webpack-study\node_modules\html-webpack-plugin\index.js:40:31)at WebpackCLI.webpack (D:\MyData\xiamy9\study\webpack-study\node_modules\webpack\lib\webpack.js:51:13)at WebpackCLI.createCompiler (D:\MyData\xiamy9\study\webpack-study\node_modules\webpack-cli\lib\webpack-cli.js:1845:29)at async WebpackCLI.buildCommand (D:\MyData\xiamy9\study\webpack-study\node_modules\webpack-cli\lib\webpack-cli.js:1952:20)at async Command.<anonymous> (D:\MyData\xiamy9\study\webpack-study\node_modules\webpack-cli\lib\webpack-cli.js:742:25)at async Promise.all (index 1)at async Command.<anonymous> (D:\MyData\xiamy9\study\webpack-study\node_modules\webpack-cli\lib\webpack-cli.js:1289:13)发现是版本问题:webpack4 和 html-webpack-plugin5配合应用了,须要将webpack降级或者html-webpack-plugin降级 。

May 31, 2021 · 1 min · jiezi

关于webpack:Webpack-Plugin知识分享

写作不易,未经作者容许禁止以任何模式转载!如果感觉文章不错,欢送关注、点赞和分享!掘金原文链接:Webpack Plugin常识分享意识PluginLoader是用于特定的模块类型进行转换;Plugin能够用于执行更加宽泛的工作,比方打包优化、资源管理、环境变量注入等;罕用PluginCleanWebpackPlugin每次批改了一些配置,从新打包时,都须要手动删除dist文件夹:咱们能够借助于一个插件来帮忙咱们实现,这个插件就是CleanWebpackPlugin;装置:npm install clean-webpack-plugin --save配置:const { CleanWebpackPlugin } = require("clean-webpack-plugin");module.exports = { entry: "./src/js/main.js", output: { filename: "bundle.js", path: path.resolve(__dirname, "build"), }, module: {...}, plugins: [new CleanWebpackPlugin()],};HtmlWebpackPlugin咱们的HTML文件是编写在根目录下的,而最终打包的dist文件夹中是没有index.html文件的。在进行我的项目部署的时,必然也是须要有对应的入口文件index.html;所以咱们也须要对index.html进行打包解决;装置npm install html-webpack-plugin --save配置可传入变量例如title,可自定义模板,template填写模板门路const HtmlWebpackPlugin = require("html-webpack-plugin");module.exports = { entry: "./src/js/main.js", output: { filename: "bundle.js", path: path.resolve(__dirname, "build"), }, module: {...}, plugins: [ new HtmlWebpackPlugin({ title: "LeBronChao Webpack", template: "./public/index.html", }), ],};模板和变量援用办法<!DOCTYPE html><html> <head> <meta charset="utf-8" /> <title><%= htmlWebpackPlugin.options.title %></title> </head> <body> <h1>LeBronChao Webpack</h1> </body></html>成果当初主动在build文件夹中,生成了一个index.html的文件该文件中也主动增加了咱们打包的bundle.js文件这个文件是如何生成的呢? ...

May 31, 2021 · 2 min · jiezi

关于webpack:初识Webpack

写作不易,未经作者容许禁止以任何模式转载!如果感觉文章不错,欢送关注、点赞和分享!博客原文链接:初识Webpack Webpack初体验用Webpack解决什么问题模块化高级个性、开发效率、安全性 ES6+、Typescript、sass、less监听文件变动并反映到浏览器上,进步开发效率开发实现后的打包,压缩、合并、tree-shaking等以及其余相干的优化Webpack是什么Webpck是一个动态的模块化打包工具,为古代的JS应用程序咱们来对下面的解释进行拆解: 打包bundler:webpack能够将帮忙咱们进行打包,所以它是一个打包工具。动态的static:这样表述的起因是咱们最终能够将代码打包成最终的动态资源(部署到动态服务器)模块化module:webpack默认反对各种模块化开发,ES Module、CommonJS、AMD等古代的modern:古代前端开发面临各种各样的问题,才催生了webpack的呈现和倒退Webpack和ViteWebpack会被Vite取代吗?vite推出后的确引起了很多的反应,也有很多人看好vite的倒退然而目前vite取代webpack还有很长的路要走 目前vue我的项目反对应用vite,也反对应用webpackvite最终打包的过程,仍然须要借助于rollup实现vite核心思想并不是独创 事实上,vite的思维和之前的snowpack是重合的,而且绝对目前来说snowpack会更加成熟当然,后续倒退来看vite可能会超过snowpackwebpack的更新迭代 webpack在倒退工程中,也会不断改进本人,借鉴其余工具的一些劣势和思维在这么多年的倒退中,无论是本身的劣势还是生态都是十分弱小的。对于Vite的思考学习任何的货色,重要的是学习核心思想 学习了JS学TS不是从0开始学习了Vue,学React也不是从0开始任何工具的呈现,都是更好地服务于咱们开发 无论是vite的呈现,还是当前新的工具呈现,不要有任何排挤的思维;咱们要粗浅地明确,工具都是为了更好地给咱们提供服务不可能呈现了某个工具,让咱们的开发效率变得更低,而这个工具却能够变得十分风行,这是不存在的Webpack默认打包咱们能够通过webpack进行打包,之后运行打包之后的代码 在目录下间接执行webpack命令 webpack 间接在终端执行webpack可能本机装置版本和我的项目版本不同,所以在package.json中定义命令例如:"build":"webpack",这样就会依据package.json中的webpack版本进行打包(前提是已install)。生成一个dist文件夹,外面寄存一个main.js文件,就是打包之后的文件 这个文件中的代码被压缩和美化了临时不关怀他是如何做到的,后续我讲webpack实现模块化原理时会再次讲到。另外发现代码中仍然存在ES6的语法,比方箭头函数、const等,这是因为默认状况下webpack并不分明咱们打包后的文件是否须要转成ES5之前的语法,后续咱们须要通过babel来进行转换和设置;发现能够失常进行打包的,然而有一个问题,webpack是如何确地入口的? 事实上,咱们运行webpack时,webpack会查找到当前目录下的src/index.js作为入口所以,如果以后我的项目中没有src/index.js,那么会报错当然也能够通过配置来指定入口和进口,例如(通常写配置文件) npx webpack --entry ./src/main.js --output-path ./build Webpack配置文件通常状况下,webpack须要打包的我的项目是非常复杂的,并且咱们须要一系列的配置来满足要求,默认配置必然是不能够的。咱们能够在根目录下创立一个webpack.config.js文件,来作为webpack的配置文件,例如const path = require("path");module.exports = { entry: "./src/main.js", output: { filename: "bundle.js", path: path.resolve(__dirname, "build"), },};继续执行webpack命令,仍然能够失常打包也能够不应用webpack.config.js作为文件名,应用命令定义门路和文件名即可,例如webpack --config ./wk.congfig.jsWebpack依赖图 webpack到底是如何对咱们的我的项目进行打包的呢?事实上webpack在解决应用程序的时候,它会依据命令或者配置文件找到入门文件;从入口开始,会生成一个依赖关系图,这个依赖关系图会蕴含应用程序中所需的所有模块(比方js文件、css文件、字体等)而后遍历图构造,打包一个个模块(依据文件的不同应用不同的loader解析)Mode配置Mode配置选项,能够告知webpack应用响应模式的内置优化:默认值是production(什么都不设置的状况下);可选值有:'none' | 'development' | 'production';这几个选项有什么样的区别呢? Mode配置代表配置了更多绿色选项 = 所有红色选项 Webpack外围流程援用于[万字总结] 一文吃透 Webpack 外围原理这个过程外围实现了 内容转换 + 资源合并 两种性能,实现上蕴含三个阶段: 初始化阶段: 初始化参数:从配置文件、 配置对象、Shell 参数中读取,与默认配置联合得出最终的参数创立编译器对象:用上一步失去的参数创立 Compiler 对象初始化编译环境:包含注入内置插件、注册各种模块工厂、初始化 RuleSet 汇合、加载配置的插件等开始编译:执行 compiler 对象的 run 办法确定入口:依据配置中的 entry 找出所有的入口文件,调用 compilition.addEntry 将入口文件转换为 dependence 对象构建阶段: ...

May 26, 2021 · 1 min · jiezi

关于webpack:Webpack-系列第三篇Dependency-Graph-深度解析

全文 2500 字,浏览时长约 30 分钟。如果感觉文章有用,欢送点赞关注,但写作实属不易,未经作者批准,禁止任何模式转载!!!背景Dependency Graph 概念来自官网 Dependency Graph | webpack 一文,原文解释是这样的: Any time one file depends on another, webpack treats this as a dependency_. This allows webpack to take non-code assets, such as images or web fonts, and also provide them as _dependencies for your application. When webpack processes your application, it starts from a list of modules defined on the command line or in its configuration file. Starting from these entry points_, webpack recursively builds a _dependency graph that includes every module your application needs, then bundles all of those modules into a small number of bundles - often, just one - to be loaded by the browser. ...

May 20, 2021 · 4 min · jiezi

关于webpack:webpack核心理念浅析

webpack核心理念浅析这段时间在推敲本人手写一个构建工具,不过在这之前,咱们先试着梳理一下webpack的理念,毕竟它山之石可以攻玉,有助于咱们想好该如何设计本人的我的项目。 简介Webpack is a static module bundler for modern JavaScript applications. 这是对于webpack的介绍,实质上,他就是一个打包器。将js模块打包成一个或者多个。实现如下代码里的能力:a.js + b.js + c.js. => bundle.js打包器呈现的起因,在此不多讲,网上有很多文章都讲过了。接下来咱们讲一讲webpack把多个js文件打包成一个bundle文件的外围思路是什么。 从构建产物反推外围流程Webpack 是一个宏大的体系,如果从源码的角度,剖析从头到尾的流程,那么就会过于简单,也没必要。毕竟咱们学习的次要是外围设计理念。那么,咱们能够试着从后果反推过程,从打包后的代码来剖析,webpack的思路。在 mode: ‘none’, devtool: ‘cheap-source-map’,的配置下,咱们能够看到打包进去的代码大略长这个样子: (function webpackUniversalModuleDefinition(root, factory) { if(typeof exports === 'object' && typeof module === 'object') module.exports = factory(); else if(typeof define === 'function' && define.amd) define([], factory); else if(typeof exports === 'object') exports["Magotan"] = factory(); else root["Magotan"] = factory();})(window, function(){ return (function(modules){ // xxxx })([ //xxxx ])['default']})不言而喻的是这是一个IIFE,简化一下,在加上具体的实现代码,就成了上面这样: ...

May 18, 2021 · 1 min · jiezi

关于webpack:译使用-Webpack-拆包的-100-正确的做法

首次公布于:https://moltemort.top/post/yi... 技术积攒,从翻译优质文章开始。本文翻译自:The 100% correct way to split your chunks with Webpack 为本人网站的用户找出推送文件的最好形式是一件很麻烦的事。 太多不同的场景,不同的技术,不同的术语了。 在这篇 Blog 中,我心愿通知你你想晓得的所有,你能够: 理解哪种文件拆分策略最适宜你的网站和用户晓得怎么去做拆包 依据 Webpack 词汇表,有两种不同类型的文件拆分形式。 这两个概念听起来能够调换,但显然并不是这样: Bundle splitting:创立更多,更小的文件(但不管怎样,每个网络申请中都要加载它们),来优化缓存。Code splitting:动静加载代码,用户能够仅下载他们正在查看的网站局部所需的代码。 第二个概念听起来更加吸引人啊,对吧?其实,许多对于此的文章都仿佛认为这是加载 JS 文件的惟一有价值的 case。 然而我来通知你,对于少数站点来说,第一个才是更有价值的形式,而且应该是你对网站所做的首要的事件。 咱们接着深刻往下看。 Bundle splittingBundle splitting 背地的想法非常简单。 如果你有一个微小的文件,当你更改了一行代码,用户必须再次下载整个文件。 然而,如果咱们将其拆分为两个文件,则用户只需下载已更改的文件,浏览器会从缓存中读取另一个文件。 值得注意的是,因为 Bundle splitting 是齐全针对缓存的,所以对于首次拜访的用户而言(拆与不拆)没什么区别。 (我认为太多的性能探讨都与首次拜访网站无关。兴许这部分是因为「第一印象很重要」,另一块是因为它很容易量化。) 当波及到频繁拜访的用户时,量化性能优化带来的影响可能很麻烦,但咱们必须量化! 上面是我在前一段中提到的状况: Alice 每周拜访咱们的网站一次,继续10周咱们每周一次发版咱们每周都会更新「产品列表」页咱们还有一个「产品详情」页,当初咱们先不论它在第5周,咱们向网站增加一个新的 npm 包第8周,咱们更新了其中一个既有的 npm 包一些人(比方我)心愿这种状况尽可能符合实际。 这种做法并不好。理论状况并不重要,咱们之后会找出起因。 (先留个铺垫!) 比拟基准值假如咱们的 JavaScript 包总大小为 400 KB,目前以单个文件main.js的模式加载。 咱们的 Webpack config 看起来像这样(省略了无关的配置内容): const path = require('path');module.exports = { entry: path.resolve(__dirname, 'src/index.js'), output: { path: path.resolve(__dirname, 'dist'), filename: '[name].[contenthash].js', },};当只有一个入口时,Webpack 会将打包后果 bundle 命名为「main.js」 ...

May 15, 2021 · 4 min · jiezi

关于webpack:webpack解决跨域及其原理

跨域问题的产生:浏览器用于断绝潜在歹意文件的平安机制-同源策略限度非同源之间的资源进行交互。webpack应用proxy解决跨域问题。基于webpack-dev-server,只适宜开发阶段。配置如下: // ./webpack.config.jsconst path = require('path')module.exports = { // ... devServer: { contentBase: path.join(__dirname, 'dist'), compress: true, port: 9000, //配置proxy proxy: { '/api': { target: 'https://api.github.com' } } // ... }}devServer外面的proxy就是对于代理的配置,该属性是一个对象,对象中的每一个规定就是一个代理的规定匹配,属性的名称是须要被代理的申请门路前缀,个别为了分别都会被设置为/api,值为对象的代理匹配规定,对应如下: target: 示意的是代理到的指标地址pathRewrite:默认状况下,咱们的/api-hy也会被写到RUL 中,如果心愿删除,能够应用 pathRewritesecure :默认状况下不承受转发到 https 的服务器上的,如果心愿反对,能够设置为 falsechangeOrigin: 它是示意是否更新代理后申请的 headers 中的 host 地址原理:proxy 工作原理上市利用 http-proxy-middleware 这个http 代理中间件,实现申请转发给其余的服务器。如下:在开发阶段,本地地址是 Http://loaclhost:3000 , 该浏览器发送一个前缀带有 /api 标识的向拂去器申请数据,然而这个服务器只是将这个申请转发给另一台服务器: const express = require('express');const proxy = require('http-proxy-middleware');const app = express();app.use('/api', proxy({target: 'http://www.example.org', changeOrigin: true}));app.listen(3000);// http://localhost:3000/api/foo/bar -> http://www.example.org/api/foo/bar 在开发阶段,webpack-dev-server 会主动启动一个本地开发服务器,所以咱们的利用在开发阶段是独立运行在 localhost 的一个端口上的,而后端服务器又是运行在另一个地址上 ...

May 11, 2021 · 1 min · jiezi

关于webpack:单页面-发版后如何通知用户端更新

【单页面 】发版后如何【告诉用户端更新】 景象形容: 首先技术栈,是vue全家桶技术栈。典型spa单页利用,每次有新性能的上线,都须要被动告诉,使用者自主刷新页面【强刷】,能力呈现新性能。产生起因: 每次打包发版【代码有变动】,index.html,网站即入口文件是变动的。 然而在单页面利用,页面跳转,都在同一个浏览器线程中,不会再一次申请index.html 资源,即便你对 index.html 资源不缓存策略,即设置响应头部信息为cache-control: no-store 也是不好使。用户还得必须刷新。 那么解决策略如何,一图胜千言: 介绍 webpack【4版本】 中 插件如何实现// 获取并注入版本号 未写点【这里还能够写 把版本号 和 我的项目 名 发送到服务器,作版本记录】const HtmlWebpackPlugin = require('html-webpack-plugin');module.exports = class WebpackVersionPlugin { constructor(options = { }) { this.options = Object.assign({ versionName: '$AppVersion' }, options) } apply(complier) { const { versionName } = this.options; complier.hooks.emit.tapAsync('WebpackVersionPlugin', (compilation, callback) => { const { hash } = compilation// 须要在 index.html 注入变量 【在htmlWebpackPlugin 钩子里解决 具体看官网文档】 HtmlWebpackPlugin.getHooks(compilation).beforeEmit.tapAsync( 'MyPlugin', (data, cb) => { const htmlScriptStr = `<script>window.${versionName}="${hash}"</script>` // 插入到第一个 script标签后面 data.html = data.html.replace(/(<script)/, `${htmlScriptStr}$1`) cb(null, data) } ) callback() }) }}成果如下: ...

May 9, 2021 · 1 min · jiezi

关于webpack:wenpack系列

模块化规范化规范webpack源码剖析1webpack源码剖析2webpack源码剖析3

May 7, 2021 · 1 min · jiezi

关于webpack:webpack源码分析3

21、定位webpack打包入口 01 cmd 文件外围的作用就组装了 node */webpack/bin/webpack.js 02 webpack.js 中外围的操作就是 require 了 node_modules/webpack-cli/bin/cli.js 03 cli.js 01 以后文件个别有二个操作,解决参数,将参数交给不同的逻辑(散发业务) 02 options 03 complier 04 complier.run( 至于run 外面做了什么,后续再看,以后只关注代码入口点 ) wepack的一个流程 合并配置 compilers.beforerun 实例化compiler compilers.run 设置node文件读写的能力 compilers.beforecompile 通过循环挂载plugins compilers.compile 解决webpack外部默认的插件(入口文件) compilers.make 22、webpack手写实现 ./webpack.jsconst Compiler = require('./Compiler')const NodeEnvironmentPlugin = require('./node/NodeEnvironmentPlugin')const webpack = function (options) {// 01 实例化 compiler 对象let compiler = new Compiler(options.context)compiler.options = options// 02 初始化 NodeEnvironmentPlugin(让compiler具体文件读写能力)new NodeEnvironmentPlugin().apply(compiler)// 03 挂载所有 plugins 插件至 compiler 对象身上if (options.plugins && Array.isArray(options.plugins)) {for (const plugin of options.plugins) {plugin.apply(compiler)}}// 04 挂载所有 webpack 内置的插件(入口)// compiler.options = new WebpackOptionsApply().process(options, compiler);// 05 返回 compiler 对象即可return compiler}module.exports = webpackconst {Tapable,AsyncSeriesHook} = require('tapable')class Compiler extends Tapable {constructor(context) {super()this.context = contextthis.hooks = {done: new AsyncSeriesHook(["stats"]),//}}run(callback) {callback(null, {toJson() {return {entries: [], // 以后次打包的入口信息chunks: [], // 以后次打包的 chunk 信息modules: [], // 模块信息assets: [], // 以后次打包最终生成的资源}}})}}module.exports = Compiler23、entryOptionPlugin ...

May 7, 2021 · 8 min · jiezi

关于webpack:万字总结-一文吃透-Webpack-核心原理

如果感觉文章有用,欢送点赞关注,但写作实属不易,未经作者批准,禁止任何模式转载!!! 背景Webpack 特地难学!!! 时至 5.0 版本之后,Webpack 功能集变得十分宏大,包含:模块打包、代码宰割、按需加载、HMR、Tree-shaking、文件监听、sourcemap、Module Federation、devServer、DLL、多过程等等,为了实现这些性能,webpack 的代码量曾经到了惊人的水平: 498 份JS文件18862 行正文73548 行代码54 个 module 类型69 个 dependency 类型162 个内置插件237 个hook在这个数量级下,源码的浏览、剖析、学习老本十分高,加上 webpack 官网语焉不详的文档,导致 webpack 的学习、上手老本极其高。为此,社区围绕着 Webpack 衍生出了各种手脚架,比方 vue-cli、create-react-app,解决“用”的问题。 但这又导致一个新的问题,大部分人在工程化方面逐步变成一个配置工程师,停留在“会用会配”然而不晓得黑盒外面到底是怎么转的阶段,遇到具体问题就瞎了: 想给根底库做个降级,呈现兼容性问题跑不动了,间接放弃想优化一下编译性能,然而不分明外部原理,无从下手究其原因还是对 webpack 外部运行机制没有造成必要的整体认知,无奈迅速定位问题 —— 对,连问题的实质都经常看不出,所谓的不能透过景象看实质,那实质是啥?我集体将 webpack 整个宏大的体系形象为三方面的常识: 构建的外围流程loader 的作用plugin 架构与罕用套路三者合作形成 webpack 的主体框架: 了解了这三块内容就算是入了个门,对 Webpack 有了一个最最根底的认知了,工作中再遇到问题也就能按图索骥了。补充一句,作为一份入门教程,本文不会开展太多 webpack 代码层面的细节 —— 我的精力也不容许,所以读者也不须要看到一堆文字就产生特地大的心理累赘。 外围流程解析首先,咱们要了解一个点,Webpack 最外围的性能: At its core, webpack is a static module bundler for modern JavaScript applications.也就是将各种类型的资源,包含图片、css、js等,转译、组合、拼接、生成 JS 格局的 bundler 文件。官网首页的动画很形象地表白了这一点: ...

May 7, 2021 · 6 min · jiezi

关于webpack:Webpack5-搭建-Vue3-TS-项目

1. 前言笔者两年前曾写过一篇文章《Webpack4 搭建 Vue 我的项目》,起初随着 webpack5 和 vue3 的面世,始终想降级下我这个 createVue 我的项目,然而苦于没有工夫(其实是因为懒),始终迁延至今。捣鼓了好几天,终于搭建好整个我的项目,因而仅以此文记录降级搭建的过程。 PS: 其实也能够用官网脚手架搭建的,为何要本人从头做起呢? 有脚手架我不必,我就折腾。哎,就是玩儿~2. 筹备工作为何降级?除了折腾外,便是享受新版本带给咱们的新个性体验。 Webpack5 的新个性长久化缓存moduleIds & chunkIds 的优化更智能的 tree shakingModule Federation...Vue3 的新个性更小更快增强 TypeScript 反对增强 API 设计一致性进步本身可维护性凋谢更多底层性能确定我的项目技术栈编程语言:TypeScript 4.2.4构建工具:[Webpack 5.33.2]()前端框架:Vue 3.0.11路由工具:Vue Router 4.0.6状态治理:Vuex 4.0.0CSS 预编译:Sass / LessHTTP 工具:AxiosGit Hook 工具:Husky + Lint-staged代码标准:EditorConfig + Prettier + ESLint提交标准:Commitlint构建部署:Travis3. 我的项目搭建此文并不是从零搭建,而是在 createVue@v1.0.0 的根底上批改搭建,如若看不懂,能够先看《Webpack4 搭建 Vue 我的项目》,跟着一步步搭建,后再看此文降级创立 createVue 文件夹,进入该文件夹, npm init 初始化我的项目老规矩,装置 webpack 四件套npm i webpack webpack-cli webpack-dev-server webpack-merge --save-dev 以后应用版本:"webpack": "^5.33.2","webpack-bundle-analyzer": "^4.4.1","webpack-cli": "^4.6.0","webpack-dev-server": "^3.11.2","webpack-merge": "^5.7.3",webpack5 启动开发服务器命令与之前有所变动,从 webpack-dev-server 转变为 webpack serve, 因而 package.json 中 script 的 start 批改为: "start": "webpack serve --progress --hot --inline --config build/webpack.dev.js" ...

April 30, 2021 · 4 min · jiezi

关于webpack:commonJS-和-ES6-模块的区别

commonJS 和 ES6 模块的区别CommonJS 输入的模块是一个值的拷贝,ES模块输入的是一个模块的援用;CommonJS 模块输入的是值的拷贝,一旦输入之后,无论模块外部怎么变动,都无奈影响之前的援用,commonJS 会缓存加载的模块,前面间接从缓存外面取值;ESModule import一个模块后生成一个援用链接,在脚本真正执行时才会依据这个援用链接去模块外面取值,模块外部的原始值变了import加载的模块也会变。CommonJS运行时加载,ESModule编译阶段援用。CommonJS在引入时是加载整个模块,生成一个对象,而后再从这个生成的对象上读取办法和属性。ESModule 不是对象,而是通过export暴露出要输入的代码块,在import时应用动态命令的办法援用指定的输入代码块,并在import语句处执行这个要输入的代码,而不是间接加载整个模块。裸露形式的区别,commonJS modules.exports = {module};ES6 export default module 或者 export module引入形式 commonJS require("module") es6 import {moduleName} from "module"

April 27, 2021 · 1 min · jiezi

关于webpack:Webpack5-模块联邦

概述1.模块联邦基于Webpack5根底上的一款插件,具备Webpack最新个性 Tree Shaking 更优Node.js polifill 给为按需加载缓存机制优化优化打包命名算法2.模块联邦能够将利用划分为更小的利用块,比方头部导航或侧边栏,也能够是数据获取逻辑的逻辑组件3.每个利用块由不同的组开发4.利用或利用快共享其余利用块或者库 新增配置项 module.exports ={ watch:true, // 增量编译 cache{ // 缓存+ type:'filesystem' // memory filesystem }, optimization:{+ moduleIds:'natural',//模块名称的生成规定+ chunkIds:'natural' //代码块名称的生成规定 }, output:{ filename:'[name.js]', //入口代码块文件名的生成规定 chunkFilename:'[name.js]'//非入口模块的生成规定 }, pulages:[ ....+ {test:/\.png$/,type:'asset/resource'},//对标file-loader+ {test:/\.ico$/,type:'asset/inline'}, //对标url-loader 模块的大小 < limit base64字符串+ {test:/\.txt$/,type:'asset/source'}, //对标raw-loader 源文件读取+ {test:/\.jpg$/,type:'asset',parser{dataurlCoundition:{maxSize:4*1024}}} // type:'asset' 示意须要webpack打包的资源 .... ] }optimization moduleIds:1.natural 按应用程序的数字ID2.named 不便调试的高可读性ID3.deterministic 依据模块名称生成简短的hash值4.size 依据模块大小生成的数字id模块联邦module.exports = { ... plugins:[ ...+ new ModuleFederationPlugin({+ name:'remoteVar',+ filename:'remoteEntry.js',+ exposes:{+ './NewsList':'./src/NewsList'+ },+ remotes:{+ host:'hostVar@http://localhost:8081/remoteEntry.js'+ },+ shared:['react','react-dom'] ]}name 必须【惟一ID】作为输入的模块名,应用的时通过 ${name}/${expose} 的形式应用,裸露在window中的全局对象;library 必须【变量】其中这里的 name 为作为 umd 的 name;filename 可选【裸露】构建出的文件名称exposes 可选【裸露】组件,示意作为 Remote 时,export 哪些属性被生产;remotes 可选【援用】示意作为 Host 时,去生产哪些 Remote;shared 可选【共享】共享池任何一方加载过,另外一方就不须要再加载了; ...

April 11, 2021 · 1 min · jiezi

关于webpack:webpack入门学习笔记03-自定义脚本帮助项目管理

1. 写在后面通过前两章博客的根底解说,咱们晓得如果想要打包编译我的项目,能够执行 npx webpack 命令,而后webpack就会依据配置文件 webpack.config.js 来对我的项目进行打包编译。然而当初咱们可能遇到以下需要: webpack的配置文件不要叫做webpack.config.js,而是叫做 webpack.config.allen.js每次打包编译的时候,都要应用 npx webpack 命令。我不喜爱这个命令,给我改成 yarn build 命令......看似都是一些很无理的要求,然而的确是咱们在架构我的项目的时候须要思考到的问题。既然如此,本篇博客就来介绍如何满足以上两个需要。 2. 指定webpack配置文件首先咱们来讲一下,如果指定webpack的配置文件。 后面提到,在打包编译我的项目的时候,咱们须要运行 npx webpack 命令,而后webpack就会依据webpack.config.js文件来进行打包编译。这里要说的是, npx webpack 命令是能够指定一些参数的,比方如果咱们想要指定webpack的配置文件为 webpack.config.allen.js ,那么能够执行以下命令: npx webpack --config webpack.config.allen.js通过下面的指令,咱们便能够应用 webpack.config.allen.js 作为webpack的配置文件,对我的项目进行打包编译。 3. 自定义脚本命令当初来解决第二个需要:如何应用 yarn build 命令来进行我的项目的打包编译。 在之前的博客中,我提到过 package.json 文件的作用,其中一个就是自定义一些脚本,而后应用 npm run 或者 yarn 来运行这些脚本,执行所定义的命令。这里咱们就能够应用这种形式,自定义脚本来进行打包编译。 新建脚本的步骤非常简单,在 package.json 文件中新建 scripts 属性,该属性为一个对象,给这个对象增加属性键值对即可新建脚本。如果要满足上述第二个需要,能够这样配置: { "name": "webpack-learning", "version": "1.0.0", "main": "index.js", "license": "MIT", "scripts": { "build": "webpack --config webpack.config.allen.js" }, "devDependencies": { "webpack": "^4.32.2", "webpack-cli": "^3.3.2" }当初自定义脚本曾经创立实现,咱们便能够通过 npm run build 或者 yarn build 来执行webpack的打包编译命令了。 ...

April 6, 2021 · 1 min · jiezi

关于vue-cli3:configureWebpack配置alias别名的两种方式

vue-cli 3.X webpack配置(resolve.alias的配置)一、configureWebpack对象模式configureWebpack:{ resolve: { // 别名配置 alias: { 'assets': '@/assets', 'common': '@/common', 'components': '@/components', 'network': '@/network', 'configs': '@/configs', 'views': '@/views', 'plugins': '@/plugins', } }},二、configureWebpack函数模式 configureWebpack: (config) => { if (process.env.NODE_ENV === 'production') { // 为生产环境批改配置... config.mode = 'production' } else { // 为生产环境批改配置... config.mode = 'development' } // 开发生产独特配置别名 Object.assign(config.resolve, { alias: { '@': path.resolve(__dirname, './src'), 'assets': path.resolve(__dirname, './src/assets'), 'common': path.resolve(__dirname, './src/common'), 'components': path.resolve(__dirname, './src/components'), 'network': path.resolve(__dirname, './src/network'), 'configs': path.resolve(__dirname, './src/configs'), 'views': path.resolve(__dirname, './src/views'), 'plugins': path.resolve(__dirname, './src/plugins'), } }) },具体阐明应用vue-cli3.x及以上版本与vue-cli2.x进行我的项目构建的区别之一,是生成的我的项目中,进行webpack配置的文件没有了。因为3.x,将大部分雷同的webpack配置,已封装到cli安装包中。 ...

April 4, 2021 · 2 min · jiezi

关于react.js:项目优化实践Webpack-动态导入-reacttoastify

本文同步公布在我的 Github 集体博客 前言如果你的我的项目正在应用 react-toastify,能够看看本文。我是最近通过webpack-bundle-analyzer发现的一个问题,其实咱们只有某个页面会可能用到弹框,比方你点了珍藏之后会有弹框出来。然而通过打包后果和运行得出,每个页面无论有没有应用,一开始都引入了 react-toastify。 react-toastify 的应用如果你关上它 Github,它是这么应用的: import React from 'react';import { ToastContainer, toast } from 'react-toastify';import 'react-toastify/dist/ReactToastify.css';function App(){ const notify = () => toast("Wow so easy!"); return ( <div> <button onClick={notify}>Notify!</button> <ToastContainer /> </div> );}而如果整个我的项目多个中央用或者须要管制好数据流的话,一个做法往往是把它拉到 Redux 治理,在咱们我的项目就变成 app.tsx // 外面封装了逻辑和返回了 <ToastContainer />import Toast from "src/containers/Toast";const { noToast } = this.propsreturn ( /* ... */ {!noToast && <Toast />})我的项目应用的是 Next.js 咱们的每个pages/页面都引入了这个app.tsx公共文件,下面代码中,Toast是通过 Redux 等封装好的 Toast组件,由下面代码粗略看出,如果在每个页面的app.tsx组件传入noToast属性,那么<Toast />就不会被加载,调用 toast办法也不会有弹框呈现。 这段代码曾经是几年前的了,揣测是这个用意,默认导入,假如确认你页面真的不须要弹框,就传noToast属性,然而我搜寻了整个我的项目,用到noToast的中央只有一个,所以这个属性并不被起初接手的人所知,也就不会手动传入noToast,导致每个页面都引入了react-toasify ...

March 27, 2021 · 1 min · jiezi

关于webpack:webpack基础及性能优化

March 26, 2021 · 0 min · jiezi

关于webpack:Webpack-Sourcemap-回顾

本文同步公布在我的 Github 集体博客 前言前几天在优化我的项目时,发现next.config.js的配置里,development 模式下的 sourcemap 为cheap-module-sourcemap,认真想了想,记忆中如同有个更举荐罕用的开发模式 sourcemap 配置:cheap-module-eval-source-map。 看了一下是三年前增加的代码,于是又回顾钻研了下 webpack 的 sourcemap 配置,开个 PR。 什么是 Sourcemap咱们的我的项目在打包后,将开发环境中源代码通过压缩,去空格,babel 编译等工程化转换,最终的我的项目代码和源代码之间差异性很大,会造成无奈 debug 的问题,在线上环境定位到的代码是压缩解决后的代码。 而 Sourcemap 就是是为了解决开发代码与理论运行代码不统一时帮忙咱们 debug 到原始开发代码的技术,解决上述代码定位的问题,是源代码和指标代码出错地位的映射。 Sourcemap 关键词Sourcemap 的关键词组合目迷五色,咱们不可能一个一个去记每种 sourcemap 用处,咱们只需晓得几个关键词的意思,便可揣测它们组合的 sourcemap 类型。 eval每一个模块都执行 eval() 过程,执行后不会生成.map文件,而是在每一个模块后追加//@ sourceURL来关联代码解决前后的对应关系。应用 eval 包裹模块代码,能够进步 rebuild 的速度。故个别 sourcemap 带有eval的选项,rebuild 速度都快一些。 webpackJsonp([1],[function(module,exports,__webpack_require__){eval( ...//# sourceURL=webpack:///./src/js/index.js?' ) },function(module,exports,__webpack_require__){eval( ...//# sourceURL=webpack:///./src/static/css/app.less?./~/.npminstall/css-loader/0.23.1/css-loader!./~/.npminstall/postcss-loader/1.1.1/postcss-loader!./~/.npminstall/less-loader/2.2.3/less-loader' ) },function(module,exports,__webpack_require__){ eval( ... //# sourceURL=webpack:///./src/tmpl/appTemplate.tpl?" ) },...]) 为什么 eval 模式 rebuild 的速度会快? 因为带 eval 的构建模式可能 cache Sourcemap,猜想可能是带 eval 的模式能把每个模块的生成代码独自打在一行里,并且都以 DataURL 的模式增加 sourcemap,这样它在 rebuild 时会对每一个模块进行查看,如果没有产生改变,就间接应用之前的 sourcemap,故只须要为改变的模块从新生成 sourcemap;而非 eval 的构建模式下生成代码不论有任何模块作出批改,都会影响到最初 bundle 文件整体的行列格局,所以它每次都要从新生成整体的 sourcemap,rebuild 的速度会很慢。source-map会为每一个打包后的模块生成独立的.map文件,会在 bundle 文件开端追加 sourceURI=指定.map文件门路,会在浏览器开发者工具中看到webpack://的文件夹 ...

March 21, 2021 · 2 min · jiezi

关于webpack:从零学脚手架三webpack属性详解

如果此篇对您有所帮忙,在此求一个star。我的项目地址: OrcasTeam/my-cli在上一篇中,介绍了 <font style="color:cornflowerblue">webpack</font> 的 entry 、 output 、 plugins 属性。 在这一篇,接着介绍其它配置属性。 mode这个属性在上一篇中应用过一次:设置 <font style="color:cornflowerblue">webpack</font> 编译模式,那么这个属性到底是什么货色呢? <font style="color:cornflowerblue">打包器</font>是将<font style="color:#007FFF">开发环境代码</font> 编译 为<font style="color:#007FFF">可部署环境代码</font> 搭建的 <font style="color:cornflowerblue">工程化</font> 代码根本都无奈间接运行在浏览器,所以本地测试也都是应用打包编译后的代码预览。 然而本地开发预览又必须具备代码可读性、可调试性等条件。 <font style="color:cornflowerblue">webpack </font>为了解决这个问题,就提供了两种 <font style="color:cornflowerblue">打包模式</font>:<font style="color:cornflowerblue">开发模式(development)</font>和<font style="color:cornflowerblue">公布模式(production)</font> 由mode属性设置 { mode:'development' }也能够应用 CLI参数 进行设置 <font style="color:cornflowerblue">webpack</font> 默认应用的是 <font style="color:cornflowerblue">公布模式(production)</font>,短少 mode 属性执行时,<font style="color:cornflowerblue">webpack</font> 会进行提醒CLI参数设置 优先级要高于 webpack.config.js 文件设置。更好的计划是应用两个 webpack.config.js 文件,脚手架个别都是这样辨别,在之后介绍 <font style="color:cornflowerblue">webpack merge</font> 时解决测试两种模式的区别时,最直观区别就是查看编译生成的代码是否进行了压缩:在 production 模式下,<font style="color:cornflowerblue">webpack</font> 会预设压缩 plugin <font style="color:cornflowerblue">webpack</font>中的 mode 属性值其实具备三个:development、production、none none 属性值与两者的区别只是没有预设任何 <font style="color:#06f">插件</font> development 和 production 两种模式只是针对不同场景下性能差异化的辨别,其实现具体的性能还是应用的 <font style="color:#06f">插件</font>为了配置简单化,development 和 production 两种模式都预设了一些根本 <font style="color:#06f">插件</font>。 ...

March 11, 2021 · 7 min · jiezi

关于webpack:从零学脚手架二初识webpack

webpack是什么打包器在应用 <font style=color:cornflowerblue>webpack </font>之前,首先须要明确 <font style="color:cornflowerblue">webpack</font> 到底是个什么货色。 简直所有文章(包含官网)中都说<font style="color:cornflowerblue">webpack</font>是一个 <font style="color:cornflowerblue">打包器</font> ,用于打包所有资源。 <font style="color:cornflowerblue">webpack</font>的确是一个 <font style="color:cornflowerblue">打包器</font> ,然而对于不晓得<font style="color:cornflowerblue">打包器</font>的敌人来说还是会有些蛊惑。 抛开 <font style="color:cornflowerblue">webpack</font> 去看问题实质。 以后时代,前端的作用越来越大,对于写过<font style="color:cornflowerblue">MVC</font>或者更早的<font style="color:cornflowerblue">JSP</font>或<font style="color:cornflowerblue">ASP.NET</font>的敌人可能更有领会,那时代的前端只是作为展现作用。 随着 <font style="color:cornflowerblue">挪动端</font>和 <font style="color:cornflowerblue">Node.JS</font> 的崛起,前端进入了新的时代。 前端与后端进行了拆散,前端开始独立部署,逐步走入了工程化的步调。 首先对于独立部署,就会有很多的工作须要实现,最容易想到的就是压缩。 <font style="color:cornflowerblue">MVC</font>时代,压缩工作都是由后端进行实现。然而对于曾经独立部署的前端,这项工作只能由前端自行实现。 当然还有逐步更新的<font style="color:cornflowerblue">JS</font>、<font style="color:cornflowerblue">CSS</font>和浏览器兼容性等一系列问题。 这些问题其实能够总结为 <font style="color:#007FFF">可部署环境代码</font> 和 <font style="color:#007FFF">开发环境代码</font> 之间的抵触。 那么能不能提供一个桥梁来连贯两种环境代码呢?最好可能提供一个 黑匣子 ,可能让咱们应用一个命令将 <font style="color:#007FFF">开发环境代码 </font>编译为 <font style="color:#007FFF">可部署环境代码</font> <font style="color:cornflowerblue">打包器</font> 就是这么一个 黑匣子 <font style="color:cornflowerblue">打包器</font>是个 黑匣子 这是对于大部分写业务的程序员来说的,他们只须要实现业务模块。 然而对于我的项目管理者,<font style="color:cornflowerblue">打包器</font> 就必须把握,毕竟因为前端的特殊性,导致须要本人配置属于本人我的项目的 <font style="color:cornflowerblue">打包器</font> 。所以对于 <font style="color:cornflowerblue">打包器</font> 的理解也根本属于前端必修课。 webpack<font style="color:cornflowerblue">webpack </font>就属于一个 <font style="color:cornflowerblue">打包器 </font>工具。目前市面上也有好多其它 <font style="color:cornflowerblue">打包器</font> 工具:grunt,gulp,rollup、还有尤大新开发vite。每一个 <font style="color:cornflowerblue">打包器</font> 都有各自的优缺点。 不过截止到目前最风行的还是<font style="color:cornflowerblue">webpack</font> 。所以在此也是以<font style="color:cornflowerblue">webpack</font>作为学习、 <font style="color:cornflowerblue">webpack</font>是一个优良的 <font style="color:#06f">JavaScript应用程序</font> 的动态模块打包器,具备高度可配置的劣势,因而也被业界称为最麻烦之一。 后面说过:<font style="color:cornflowerblue">打包器</font> 就是将 <font style="color:#007FFF">开发环境代码</font> 进行编译为 <font style="color:#007FFF">可部署环境代码</font> 。 而不同的我的项目对 <font style="color:#007FFF">可部署环境代码</font> 的要求又不统一。所以 <font style="color:cornflowerblue">webpack</font> 并没有提供一个全而大性能,而只是提供了一个 <font style="color:#06f">外围引擎</font>, 只负责 <font style="color:cornflowerblue">JS</font> 文件的依赖打包,其它性能应用 <font style="color:#06f">插件化</font> 进行配置 。 ...

March 9, 2021 · 6 min · jiezi

关于webpack:vscode支持webpack-alias的路径跳转

应用了webpack alias配置门路别名之后,vscode就无奈感知到别名的理论物理门路,导致无奈cmd+鼠标 来智能跳转到定义。通过vscode的jsconfig文件配置后,能够让vscode持续反对跳转。 jsconfig.json放在我的项目根目录下,paths外面配置门路别名,但配置时要加通配符(跟webpack有区别),key示意门路别名,value示意理论物理门路。基门路是 baseurl exclude示意让vscode排除掉的resolve门路,以防止影响性能。

March 3, 2021 · 1 min · jiezi

关于webpack:使用webpack和rollup打包组件库

前言之前做了一个loading的款式组件,为了实现代码的可重用性,将这个小我的项目打包并且公布在了npm上。在一次次的打包发包过程中经验了一个有一个报错,@buzuosheng/loading这个组件曾经到了2.7.0版本,尽管还有一些要调整的中央,但总算是能够用了。 webpack和rollup比照webpack算是应用程序员应用最多的打包工具,面试中往往会问到webpack的相干问题,而rollup被问到的要少很多。导致这种景象的一个起因是,利用开发应用webpack,库开发应用rollup的说法。 然而两个打包工具都有很弱小的插件开发性能,性能差别越来越含糊,然而rollup应用起来更加简洁,而且能打出能小体积的文件。但当咱们做前端利用时,性能剖析往往要求更小的库,所以rollup更合乎开发库的要求。 这次算是一个打包的试验,咱们应用两个工具都对这个我的项目打一次包。 应用webpack打包在打包之前,须要给package.json文件中增加或更改一些字段。 { // 程序主入口模块,用户援用的就是该模块的导出 "main": "dist/bundle.js", // 我的项目蕴含的文件 "files": [ "src", "dist" ], // 将react和react-dom挪动到该配置中,兼容依赖 "peerDependencies": { "react": "^17.0.1", "react-dom": "^17.0.1" },}webpack打包须要用到很多库来解决不同的文件,这个我的项目比拟小,就只用了两个库。 // webpack.config.jsconst path = require('path');const MiniCssExtractPlugin = require("mini-css-extract-plugin");module.exports = { mode: 'production', entry: './src/Loading.jsx', output: { filename: "index.js", path: path.join(__dirname, "./dist/"), libraryTarget: 'umd', }, optimization: { minimize: false, }, resolve: { extensions: ['.jsx'] }, module: { rules: [ { test: /\.css$/, loader: [MiniCssExtractPlugin.loader, 'css-loader?modules'], }, { test: /\.(js|jsx)$/, loader: "babel-loader", exclude: /node_modules/, }, ] }, plugins: [ new MiniCssExtractPlugin({ filename: "main.min.css" // 提取后的css的文件名 }) ],}原本应该写开发和生产两个环境下的配置,但在这里只写了production环境下的配置。 ...

February 24, 2021 · 1 min · jiezi

关于webpack:粗涉Webpack

Webpack记录文档概念: webpack 是一个古代 JavaScript 应用程序的动态模块打包器(module bundler)。当 webpack 解决应用程序时,它会递归地构建一个依赖关系图(dependency graph),其中蕴含应用程序须要的每个模块,而后将所有这些模块打包成一个或多个 bundle。打包第一个文件: 全局装置webpack: npm install webpack -g新建一个文件夹放入两个文件,一个为html一个为就是文件,其中HTML引入该js文件打包后的文件名执行webpack js文件 打包后的文件名此时如果呈现报错: Cannot find module 'webpack-cli'请执行: npm install --save-dev webpack再执行呈现: WARNING in configuration The 'mode' option has not been set, webpack will fallback to 'production' for this value. Set 'mode' option to 'development' or 'production' to enable defaults for each environment.请先执行 npm init -y, 生成package.json在新建一个webpack.config.js配置文件,用于配置webpack选项写入:const path = require('path')// 通过Node模块,向里面裸露一个配置module.exports = { entry:path.join(__dirname, './src/main.js'), // 打包文件 output: { path: path.join(__dirname, './dist') // 打包好的文件名 }, mode: 'development' // 设置mode}此时再执行打包将无报错,且生成的文件将放入当前目录下的dist文件夹, 默认文件名为main.js ...

February 23, 2021 · 3 min · jiezi

关于webpack:前端基础知识总结四-webpack

Webpack几个概念: module: 模块,在webpack眼里,任何能够被导入导出的文件都是一个模块。chunk: chunk是webpack拆分进去的: entry chunk:每个入口文件都是一个chunk通过 import、require 引入的代码children chunk:通过 splitChunks 拆分进去的代码commons chunk: 通过CommonsChunkPlugin创立进去的文件bundle: webpack打包进去的文件,也能够了解为就是对chunk编译压缩打包等解决后的产出。webpack 优化问题剖析: 外围问题:多页利用打包后代码冗余,文件体积大。根本原因:雷同模块在不同入口之间没有失去复用,bundle之间比拟独立。解决思路: 解决代码冗余。把不同入口之间,独特援用的模块,抽离进去,放到一个公共模块中。这样不论这个模块被多少个入口援用,都只会在最终打包后果中呈现一次。减小文件体积。当把这些独特援用的模块都堆在一个模块中,这个文件可能异样微小,也是不利于网络申请和页面加载的。所以咱们须要把这个公共模块再依照肯定规定进一步拆分成几个模块文件。如何拆分,形式因人而异,因我的项目而异。拆分准则有: 业务代码和第三方库拆散打包,实现代码宰割;业务代码中的公共业务模块提取打包到一个模块;第三方库最好也不要全副打包到一个文件中,因为第三方库加起来通常会很大。能够把特地大的库独立打包,剩下的加起来如果还很大,就把它依照肯定大小切割成若干模块。提取公共模块通过将公共模块拆出来,最终合成的文件在最开始的时候加载一次,便存到缓存中供后续应用。这个带来速度上的晋升,因为浏览器会迅速将公共的代码从缓存中取出来,而不是每次拜访一个新页面时,再去加载一个更大的文件。 webpack提供了一个十分好的内置插件帮咱们实现这一需要:CommonsChunkPlugin。不过在 webpack4 中CommonsChunkPlugin被删除,取而代之的是optimization.splitChunks。CommonsChunkPluginCommonsChunkPlugin 插件,是一个可选的用于建设一个独立文件(又称作 chunk)的性能,这个文件包含多个入口 chunk 的公共模块。 配置选项:name:能够是曾经存在的chunk(个别指入口文件)对应的name,那么就会把公共模块代码合并到这个chunk上;否则,会创立名字为name的commons chunk进行合并filename:指定commons chunk的文件名chunks:指定source chunk,即指定从哪些chunk当中去找公共模块,省略该选项的时候,默认就是entry chunkschildren 指定为true的时候,就代表source chunks是通过entry chunks(入口文件)进行code split进去的children chunkschildren和chunks不能同时设置,因为它们都是指定source chunks的children 能够用来把 entry chunk 创立的 children chunks 的共用模块合并到本身,但这会导致初始加载工夫较长async:即解决children:true时合并到entry chunks本身时初始加载工夫过长的问题。async设为true时,commons chunk 将不会合并到本身,而是应用一个新的异步的commons chunk。当这个children chunk 被下载时,主动并行下载该commons chunkminChunks:既能够是数字,也能够是函数,还能够是Infinity, 默认值是2minChunks含意: 数字:模块被多少个chunk公共援用才被抽取进去成为commons chunk 函数:承受 (module, count) 两个参数,返回一个布尔值,你能够在函数内进行你规定好的逻辑来决定某个模块是否提取成为commons chunk Infinity:只有当入口文件(entry chunks) >= 3 才失效,用来在第三方库中拆散自定义的公共模块根本应用1. 拆散出第三方库、自定义公共模块、webpack运行文件, 放在同一个文件中 批改webpack.config.js新增一个入口文件vendor, 应用CommonsChunkPlugin插件进行公共模块的提取: const path = require("path");const webpack = require("webpack");const packageJson = require("./package.json");module.exports = { entry: { first: './src/first.js', second: './src/second.js', // 新增一个入口文件vendor vendor: Object.keys(packageJson.dependencies) }, output: { path: path.resolve(__dirname,'./dist'), filename: '[name].js' }, plugins: [ // 应用CommonsChunkPlugin插件进行公共模块的提取 new webpack.optimize.CommonsChunkPlugin({ name: 'vendor', filename: '[name].js' }), ]}生成dist文件夹下文件有:first.js, second.js, vendor.js。 ...

February 22, 2021 · 5 min · jiezi

关于webpack:Webpack配置环境变量

在理论我的项目开发中,须要基于多种环境去设置不同的环境变量以便于在构建阶段或是运行阶段去应用,例如常见的通过process.env.NODE_ENV在构建时去判断以后的构建环境是development还是production,例如须要在开发环境、测试环境和生产环境去拜访不同的接口服务器。 为了模仿实在的我的项目,应用webpack搭建了一个最小化的我的项目构造: ├─package.json├─src| └index.jsx├─public| └index.html├─config| └webpack.config.jsNode环境变量Node环境变量就是指process.env这个属性 process.env 是什么?它是 Nodejs 应用程序中,process.env 属性,返回蕴含用户环境的对象,所以它不能够在客户端侧代码中应用,也就不能在浏览器环境上应用。 // process.env(官网示例){ TERM: 'xterm-256color', SHELL: '/usr/local/bin/bash', USER: 'nodejscn', PATH: '~/.bin/:/usr/bin:/bin:/usr/sbin:/sbin:/usr/local/bin', PWD: '/Users/nodejscn', EDITOR: 'vim', SHLVL: '1', HOME: '/Users/nodejscn', LOGNAME: 'nodejscn', _: '/usr/local/bin/node'}批改Node环境变量1. 批改 package.json 文件应用 cross-env依赖包,反对跨平台配置环境变量。 // package.json{ ..., "scripts": { "start": "npm run dev", "dev": "cross-env NODE_ENV=development AAA=123 webpack serve --config ./config/webpack.config.js", "build:test": "cross-env NODE_ENV=test webpack --config ./config/webpack.config.js", "build:pro": "cross-env NODE_ENV=production webpack --config ./config/webpack.config.js" }, ...}通过在package.json脚本中设置变量的形式来注入环境变量,同时cross-env还反对去设置多个环境变量,只须要通过空格辨别,例如在dev脚本中设置的NODE_ENV=development和AAA=123。 这样在执行npm start就可能通过process.env获取到对应的环境变量。 ...

February 18, 2021 · 2 min · jiezi

关于webpack:认识和理解webpack

https://blog.csdn.net/hope_It...

February 3, 2021 · 1 min · jiezi

关于webpack:一文搞懂-webpack-懒加载机制-webpack-系列

webpack 是一个古代 JavaScript 应用程序的动态模块打包器 (module bundler)。当 webpack 解决应用程序时,它会递归地构建一个依赖关系图 (dependency graph),其中蕴含应用程序须要的每个模块,而后将所有这些模块打包成一个或多个 bundle。 前端工程化演进到明天,webpack 做了很大的奉献。我的项目工程化带来了很多便捷,咱们不再须要手动解决依赖之间的关系,也能够更不便的应用更多好用的框架,咱们能够更关注业务自身,集中精力打造咱们的产品。 在 webpack 中,应用懒加载或者按需加载,是一种很好的优化网页或利用的形式。这种形式实际上是先把你的代码在一些逻辑断点处罚来到,而后在一些代码块中实现某些操作后,立刻援用或行将援用另外一些新的代码块。这样放慢了利用的初始加载速度,加重了它的总体体积,因为某些代码块可能永远不会被加载。 那么,接下来让咱们来探索一下 webpack 对懒加载的模块做了哪些工作吧~ 实现背景咱们先假如咱们在实现一个实在的我的项目,这个我的项目中有上传下载性能。 下载性能个别是关上一个链接,所以咱们间接实现在主包中。而上传性能可能会应用到第三方 sdk,咱们应用懒加载进行加载。只有在用户点击上传时,咱们才会加载这个具备上传性能的包,来进行上传。 上传下载性能可能会应用到一些第三方 sdk,而这些第三方 sdk 的体积往往十分大,并且这个性能所以这个性能做成懒加载实现是正当的。为了演示差异,咱们这里将“下载”和“上传”两个性能做辨别。 我的项目根底配置咱们先搭建一个根底的 webpack 配置,让其反对懒加载配置,而后咱们间接通过打包后的代码来看看懒加载实现的成果。咱们须要有个根底目录配置,我的项目 Demo 目录构造如下: 文件/目录阐明src入口文件、下载模块、上传模块index.htmlhtml 模板文件webpack.config.jswebpack 配置文件package.json我的项目阐明文件性能代码实现咱们先来看看咱们的性能代码实现吧,别离是 download.js、upload.js、index.js。 // ./src/download.jsconst download = () => { console.log("download start"); console.log("schedule download sdk"); console.log("download");}export default download;// ./src/upload.jsconst upload = () => { console.log("upload start"); console.log("schedule upload sdk"); console.log("upload");}export default upload;// ./src/index.jsimport download from "./download";console.log("initial page");async function handlerUploadClick() { // 动静加载 upload 模块,该模块的 default 属性就是 upload 办法 const { default: upload } = await import("./upload"); // 调用 upload 办法 upload();}async function handlerDownloadClick() { download();}// 点击 upload 按钮时,调用上传办法document.querySelector("#upload").addEventListener("click", handlerUploadClick, false)// 点击 download 按钮时,调用下载办法document.querySelector("#download").addEventListener("click", handlerDownloadClick, false)<!-- index.html --><!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta http-equiv="X-UA-Compatible" content="ie=edge"> <title>Webpack LazyLoad</title></head><body> <section> <h1>Home</h1> <button id="upload">Upload</button> <button id="download">Download</button> </section></body></html>在咱们的性能代码实现中,咱们实现了一个 html 网页,其中有两个按钮,一个是上传按钮,一个是下载按钮。 ...

February 2, 2021 · 2 min · jiezi

关于webpack:webpack体积怎么优化有哪些方法

1)去掉不必要的插件 开发环境和生产环境应用同一个webpack配置文件,导致生产环境打包的js文件蕴含很多没必要的插件(如:NoEmitOnErrorsPlugin) 2)提取第三方库 第三方库和源代码在一起打包体积会很大 CommonsChunkPlugin 提取代码中公共模块,而后将公共模块打包到一个独立的文件中,以便在其余的入口和模块中应用。 3)代码压缩 内置插件UglifyPlugin,退出这个插件编译速度会变慢,所以个别只在生产环境启用 4)代码宰割(webpack的code split配合router) ·webpack的code spliting个性能够将代码库宰割成按需加载的块(chunks) ·AMD/commmonJS指定不同的办法去做代码按需加载,他们反对代码宰割并充当宰割点 ·不反对es6的模块零碎 5)设置缓存 对于动态文件,第一次获取之后,文件内容没有扭转的话间接读取缓存,然而如果缓存工夫过长文件要更新的话能够打包后的文件名退出hash值。

February 1, 2021 · 1 min · jiezi

关于webpack:Webpack学习笔记

Webpack学习Webpack 配置我的项目流程npm init (初始化)npm i webpack webpack-cli -D (我的项目装置webpack和webpack-cli)npm i style-loader css-loader less less-loader -D (装置打包款式资源所需的loader)npm i html-webpack-plugin -D (打包html的插件 这里我用 html-webpack-plugin@next )npm i html-loader url-loader file-loader -D (打包图片资源)npm i mini-css-extract-plugin -D (插件 提取css成独自文件)npm i postcss-loader postcss-preset-env -D (css兼容性解决)npm i webpack-dev-server -D (开启服务器 热更新 自动化 开启指令 npx webpack serve)npm i optimize-css-assets-webpack-plugin -D (压缩css)npm i babel-loader @babel/core @babel/preset-env core-js -D (js兼容性解决)npm i eslint-loader eslint eslint-config-airbnb-base eslint-plugin-import -D (js语法查看 eslint)**p3 Webpack 五个外围概念**1. Entry 入口 :批示终点打包文件2. Output 输入:批示打包后资源bundles的输入3. Loader 转化器:将非js文件转化为浏览器了解的4. Plugins 插件:有执行很多工作,范畴有:打包优化和压缩。5. Mode 模式:有 开发(developm)和生产(production)模式**p4 打包指令**webpack ./src/index.js -o ./build/built.js --mode=developmentwebpack.json 中加上"scripts": {    "dev": "webpack --mode development",    "build": "webpack --mode production"  },**开发环境:npm run dev****生产环境:npm run build**运行后果:node /bundle.js文件**论断*** webpack能解决js、json资源,不能解决css、img等其余资源* 生产和开发环境将ES6模块化编译成浏览器能辨认的模块化* 生产环境比开发环境多一个压缩js代码**p5 打包款式资源**webpack.config.js 是 webpack的配置文件作用:批示 webpack 干哪些活(当你运行 webpack 指令时,会加载外面的配置)所有构建工具都是基于NodeJs平台运行的,模块化默认采纳CommonJs**款式须要下载**style-loadercss-loaderlessless-loader**p6 打包html资源**须要下载插件html-webpack-plugin援用const HtmlWebpackPlugin = require("html-webpack-plugin");module.exports = {...。        plugins: [        new HtmlWebpackPlugin({            template: "./src/index.html"        })    ],}**p7 打包图片资源**下载url-loaderfile-loaderhtml-loader**p8 打包其余资源**module.exports = {...module: {        rules: [            // 打包其余资源            {                // 排除css/js/html资源                exclude:/.(css|js|html)$/,                loader: 'file-loader'            }        ]    },}**p9 开启服务器 热更新 自动化**下载webpack-dev-server开启指令npx webpack serve**p12 提取css成单文件**下载插件mini-css-extract-plugin**p13 css兼容性解决**下载 库postcss-loaderpostcss-preset-env有时报错须要回退 npm i postcss-loader@3.0.0 -D**p14 压缩css**下载插件optimize-css-assets-webpack-plugin**p14 js语法查看**下载eslint-loadereslinteslint-config-airbnb-baseeslint-plugin-import还要配置 package.json文件"eslintConfig":{    "extends": "airbnb-base"  }**p14 js兼容性解决**下载babel-loader@babel/core@babel/preset-envcore-js根本js兼容解决 @babel/preset-env全副js兼容解决( 间接在js引入即可 ) @babel/polyfill最优解按需下载 core-js**p20 HMR 模块热更新**devServer : {...hot: true;}入口文件中if (module.hot) {    // 一旦 module.hot 为true,阐明开启了HMR性能。 --> 让HMR性能代码失效    module.hot.accept('./print.js', function() {      // 办法会监听 print.js 文件的变动,一旦发生变化,其余模块不会从新打包构建。      // 会执行前面的回调函数      print();    });  }

January 27, 2021 · 1 min · jiezi

关于webpack:webpack-误区

1. webpack 编译es module不依赖babel始终认为但凡ES6的代码编译为ES5都是要通过babel,而后做了尝试,运行webpack首页代码,并没有配置babel,编译进去的代码照样能够跑,这里webpack的编译指标环境为web,(即是默认的指标环境,其余的环境还没测试),尽管es module不依赖babel,然而其余ES6的语法是要靠babel能力编译到ES5的。比方const =>

January 22, 2021 · 1 min · jiezi

关于webpack:YYDS-Webpack-Plugin开发

@[toc] 作为一名踏足前端工夫不长的小开发必须得聊一聊webpack,刚开始接触webpack时第一反馈这是啥(⊙_⊙)? 怎么这么简单,感觉好难呀,算了先不论这些!工夫是个好货色呀,随着对前端工程化的实际和了解缓缓加深,跟webpack接触越来越多,最终还是被ta折服,不禁高呼一声“webpack yyds(永远滴神)!” 去年年中就想写一些对于webpack的文章,因为各种起因耽误了(次要是感觉对webpack了解还不够,不敢妄自下笔);邻近年节,工夫也有些了,与其 "摸鱼"不如摸摸webpack,整顿一些"年货"分享给须要的xdm!后续会持续写一些【 Webpack】系列文章,xdm监督··· 导读 本文次要通过实现一个cdn优化的插件CdnPluginInject介绍下webpack的插件plugin开发的具体流程,两头会波及到html-webpack-plugin插件的应用、vue/cli3+我的项目中webpack插件的配置以及webpack相干知识点的阐明。全文大略2800+字,预计耗时5~10分钟,心愿xdm看完有所学、有所思、有所输入! 留神:文章中实例基于vue/cli3+工程开展! 一、cdn惯例应用index.html: <head> ···</head><body> <div id="app"></div> <script src="https://cdn.bootcss.com/vuex/3.1.0/vuex.min.js"></script> <script src="https://cdn.bootcss.com/vue-router/3.0.2/vue-router.min.js"></script> ···</body>vue.config.js: module.exports = { ··· configureWebpack: { ··· externals: { 'vuex': 'Vuex', 'vue-router': 'VueRouter', ··· } },二、开发一个webpack pluginwebpack官网如此介绍到:插件向第三方开发者提供了 webpack 引擎中残缺的能力。应用阶段式的构建回调,开发者能够引入它们本人的行为到 webpack 构建流程中。创立插件比创立 loader 更加高级,因为你将须要了解一些 webpack 底层的外部个性来实现相应的钩子! 一个插件由以下形成: 一个具名 JavaScript 函数。在它的原型上定义 apply 办法。指定一个涉及到 webpack 自身的 事件钩子。操作 webpack 外部的实例特定数据。在实现性能后调用 webpack 提供的 callback。// 一个 JavaScript classclass MyExampleWebpackPlugin {// 将 `apply` 定义为其原型办法,此办法以 compiler 作为参数 apply(compiler) { // 指定要附加到的事件钩子函数 compiler.hooks.emit.tapAsync( 'MyExampleWebpackPlugin', (compilation, callback) => { console.log('This is an example plugin!'); console.log('Here’s the `compilation` object which represents a single build of assets:', compilation); // 应用 webpack 提供的 plugin API 操作构建后果 compilation.addModule(/* ... */); callback(); } ); }}三、cdn优化插件实现思路: ...

January 19, 2021 · 4 min · jiezi

关于webpack:webpack5源码导读如何实现自定义-target

开发者能够通过 快利用转换工具 将本人的小程序源码一键转换为快利用转换版,而后上传本人的 rpk 包,审核通过后即能够在数亿安卓设施上运行本人的快利用。而快利用打包工具是构建于 webpack 之上的一个模块代码打包零碎,通过降级 webpack5 ,应用 webpack5 的长久化缓存,无望给快利用转换工具带来微小的性能晋升。更多优质博文请拜访快利用官网博客 webpack5 正式版曾经公布三个月了,目前最新版本是 5.11.1。具体的迁徙指南请参考 webpack 官网的文档: Webpack 5 releasemigrating to webpack 5倡议参考 webpack 官网的这些文档,比参考一些不齐全、不精确的翻译无效的多,惟一的问题是有可能每个词都意识,连在一起却不晓得是什么意思。 1. 浏览源码的初衷在 webpack4 中, target 选项能够设置为 function,以实现自定义的代码生成形式。然而在 webpack5 中,target 只能设置为特定的字符串或字符串数组了。最坑的是,此性能间接就废除了,webpack 没有给任何过渡提醒。而在咱们的打包工具中,一些重要的性能是通过自定义 target 来实现的。所以咱们须要钻研 webpack5 源码来摸索一种代替的实现形式。 2. 本文写作的初衷本文并不是一篇根底的 webpack5 配置教程, webpack5 配置参考下面介绍的官网文档即可。本文想要展现的有三点: Webpack5 的性能晋升有多大?最终降级 webpack5 后,配合 webpack5 的长久化缓存,打包工具的二次打包速度绝对于应用 cache-loader 缓存进步了 40%,二次打包内存占用绝对于应用 cache-loader 缓存二次打包内存占用绝对于应用 cache-loader 缓存升高了 40%,绝对于不应用任何缓存,打包工具的二次打包速度进步了约 70%,二次打包内存占用升高了约 70%。 为什么咱们须要浏览源码?家喻户晓 webpack 的官网文档是有些烂的,中文文档更是烂的不行。如果你屡次浏览文档之后还是不分明某项配置应该怎么配,或者咱们有一些非凡的性能需要(比方实现与 webpack4 中一样的 target 为 function 时的性能),兴许你须要看看源码了。 ...

January 7, 2021 · 6 min · jiezi

关于webpack:面试官webpack原理都不会

引言前一段时间我把webpack源码大略读了一遍,webpack 到4.x版本后,其源码曾经比拟宏大,对各种开发场景进行了高度形象,浏览老本也愈发低廉。 适度剖析源码对于大家并没有太大的帮忙。本文次要是想通过剖析webpack的构建流程以及实现一个简略的webpack来让大家对webpack的外部原理有一个大略的理解。(保障能看懂,不懂你打我 ????) webpack 构建流程剖析首先,毋庸多言,上图~webpack 的运行流程是一个串行的过程,从启动到完结会顺次执行以下流程:首先会从配置文件和 Shell 语句中读取与合并参数,并初始化须要应用的插件和配置插件等执行环境所须要的参数;初始化实现后会调用Compiler的run来真正启动webpack编译构建过程,webpack的构建流程包含compile、make、build、seal、emit阶段,执行完这些阶段就实现了构建过程。 初始化entry-options 启动从配置文件和 Shell 语句中读取与合并参数,得出最终的参数。 run 实例化compiler:用上一步失去的参数初始化 Compiler 对象,加载所有配置的插件,执行对象的 run 办法开始执行编译 编译构建entry 确定入口依据配置中的 entry 找出所有的入口文件 make 编译模块从入口文件登程,调用所有配置的 Loader 对模块进行翻译,再找出该模块依赖的模块,再递归本步骤直到所有入口依赖的文件都通过了本步骤的解决 build module 实现模块编译通过下面一步应用 Loader 翻译完所有模块后,失去了每个模块被翻译后的最终内容以及它们之间的依赖关系 seal 输入资源依据入口和模块之间的依赖关系,组装成一个个蕴含多个模块的 Chunk,再把每个 Chunk 转换成一个独自的文件退出到输入列表,这步是能够批改输入内容的最初机会 emit 输入实现在确定好输入内容后,依据配置确定输入的门路和文件名,把文件内容写入到文件系统 剖析完构建流程,上面让咱们本人入手实现一个繁难的webpack吧~ 实现一个繁难的 webpack筹备工作目录构造咱们先来初始化一个我的项目,构造如下: |-- forestpack |-- dist | |-- bundle.js | |-- index.html |-- lib | |-- compiler.js | |-- index.js | |-- parser.js | |-- test.js |-- src | |-- greeting.js | |-- index.js |-- forstpack.config.js |-- package.json这里我先解释下每个文件/文件夹对应的含意: ...

January 4, 2021 · 4 min · jiezi

关于webpack:webpack5优化

目录一、构建优化(压缩代码)二、长期缓存(hash)三、长久缓存(增量构建)四、webpack5新个性五、总结 一、构建优化(压缩代码)1、Tree Shaking(1)usedExports : true 标记出未被导出的变量(2)minimize : true 去除无用变量并压缩代码 2、合并模块optimization.concatenateModules = true 3、副作用sideEffects(1)optimization.sideEffects = true 开启副作用性能(2)package.json 中设置 sideEffects : false 标记所有模块无副作用 4、webpack5改良(1)嵌套的 tree-shaking这个例子能够在生产模式下删除导出的b(2)外部模块 tree-shaking webpack5中有一个新选项 optimization.innerGraph,在生产模式下默认开启,能够对模块中的标记进行剖析,找出导出和援用之间的依赖关系。 外部依赖图算法会找出 something 只有在应用 test 导出时才会应用。这容许将更多的进口标记为未应用,并从代码包中省略更多的代码。当设置"sideEffects": false时,若test 导出未被应用时,./something 将被省略。(3)其它优化 CommonJs Tree Shaking副作用剖析:能够依据对源代码的动态剖析,主动将模块标记为无副作用模块合并:反对更多模块,如 ExternalModules 和 json 模块通用 Tree Shaking 改良export * 曾经改良,能够跟踪更多的信息,并且不再将默认导出标记为应用改良代码生成会生成更短的代码 Object(...)->(0, ...)合并运行时函数 r.d(x, "a", () => a); r.d(x, "b", () => b); -> r.d(x, {a: () => a, b: () => b});二、长期缓存(hash)1、哈希hash所有chunk文件应用雷同的hash我的项目中任一文件内容发生变化都会影响所有chunk文件hash ...

December 27, 2020 · 1 min · jiezi

关于webpack:编译的速度与激情从10mins到1s

原文:编译的速度与激情:从10mins到1s | AlloyTeam作者:glendonli导语:对于大型前端我的项目而言,构建的稳定性和易用性至关重要,腾讯文档在迭代过程中,简单的我的项目构造和编译带来的问题日益增多,极大的减少了新人上手与日常搬砖的开销。恰逢 Webpack5 上线,不如来一次彻底的魔改~1.前言腾讯文档最近基于刚刚公布的 Webpack5 进行了一次编译的大重构,作为一个多个仓库独特形成的大型项目,任意品类的代码量都超过百万。对于腾讯文档这样一个疾速迭代,高度依赖自动化流水线,长年并行多个大型需要和有数小需要的我的项目来说,稳固且疾速的编译对于开发效率至关重要。 这篇文章,就是笔者最近进行重构,胜利将日常开发优化到 1s 的过程中,遇到的一些大型项目特有的问题和思考,心愿能给大家在前端我的项目构建的优化中带来一些参考和启发。 2.大型项目编译之痛随着我的项目体系的逐步扩充,往往会遇到旧的编译配置无奈反对新个性,因为各种 config 文件自带的浏览 debuff,以及累累的技术债,大家总会趋于不去批改旧配置,而是试图新增一些配置在外围对编译系统进行修改。也是这样相似的起因,腾讯文档过来的编译编译也并不优雅: 多级的子仓库构造,简单的编译系统造成很高的了解和改变老本,也带来了较高的编译耗时,对于整个团队的开发效率有着不小的影响。 3.All in One为了解决编译简单和迟缓的问题,至关重要的,就是禁止套娃:多层级混合的零碎必须破除,对立的编译才是王道。在所有编译系统中,Webpack 在大我的项目的打包上具备很强劣势,插件零碎最为饱满,并且 Webpack5 的带来了 Module Federation 新个性,因而笔者抉择了用 Webpack 来统合多个子仓库的编译。 3.1.整合基于 lerna 的仓库构造腾讯文档应用了 lerna 来治理仓库中的子包,应用 lerna 的益处此处就不作开展了。不过 lerna 的通用用法也带来了肯定的问题,lerna 将一个仓库变成了构造上的多个仓库,如果依照默认的应用形式,每个仓库都会有本人的编译配置,单个我的项目的编译变成了多个我的项目的联编联调,批改配置和增量优化都会变得比拟艰难。 尽管应用 lerna 的目标是使各个子包绝对独立,然而在整个我的项目的编译调试中,往往须要的是所有包的汇合,那么,笔者就能够疏忽掉这个子包间的物理隔离,把子仓库作为子目录来对待。不依赖 lerna,笔者须要解决的,是子包间的援用问题: /** package/layout/src/xxx.ts **/import { Stream } from "@core/model";// do something事实上,笔者能够通过 webpack 配置中 resolve 的 alias 属性来达到相应成果: { resolve: { alias: { '@core/model': 'word/package/model/src/', } }}3.2.治理游离于打包零碎之外的文件在大型项目中,有时会存在一些非凡的动态代码文件,它们往往并不参加到打包零碎中,而是由其余形式间接引入 html,或者合并到最终的后果中。 ...

December 22, 2020 · 5 min · jiezi

关于webpack:webpack解决样式url背景图问题

定位谬误我的项目应用webpack4进行编译,打包后的款式中应用url办法指定的背景图片不可能失常显示 .bgurl{ background-image: url('/images/abc.jpeg')}上述款式在webpack中编译出错,配置如下 // stylus[ loader: MiniCssExtractPlugin.loader, { loader: 'css-loader', options: { importLoaders: 2, } }, 'postcss-loader', 'stylus-loader']始终爆图片未找到的谬误,依照网上找到的解决方案,补全MiniCssExtractPlugin配置项publicPath,但仍然出错。看来问题不是出在MiniCssExtractPlugin。后通过认真排查。定位到谬误其实是css-loader编译时爆进去的。 去npm上找到css-loader配置,找到如下内容 NameTypeDefaultDescriptionurl{Boolean\Function}trueEnables/Disables url/image-set functions handlingurl Type: Boolean|Function Default: true Enables/Disables url/image-set functions handling. Control url() resolving. Absolute URLs are not resolving. Examples resolutions: url(image.png) => require('./image.png')url('image.png') => require('./image.png')url(./image.png) => require('./image.png')url('./image.png') => require('./image.png')url('http://dontwritehorriblecode.com/2112.png') => require('http://dontwritehorriblecode.com/2112.png')image-set(url('image2x.png') 1x, url('image1x.png') 2x) => require('./image1x.png') and require('./image2x.png')属性url默认为true,此属性默认强行解释款式中应用url定位的图片,默认寻址该图片地址(与css同源地址),因同源地址图片不存在(理论图片存在于另外的目录),造成编译谬误。 修改webpack配置[ { loader: MiniCssExtractPlugin.loader, options: { publicPath: '//localhost:3000/', } }, { loader: 'css-loader', options: { importLoaders: 2, url: false } }, 'postcss-loader', 'stylus-loader']publicPath 此项配置能够共用webpack.output配置,但倡议在MiniCssExtractPlugin.loader中独立设置。有以下两个起因 ...

December 21, 2020 · 1 min · jiezi

关于webpack:webpack-学习笔记五plugins-配置

plugins,是 webpack 中另一个很重要的性能。 为什么要应用 pluginsplugins 的作用就是用来拓展 webpack 性能的,它会在整个我的项目构建过程中失效,执行相干的工作。 plugins 和 loaders 的区别在于,loaders 是在打包构建过程中用来解决源文件的(例如:JSX、sass、less...);而 plugins 插件并不间接操作单个文件,而是间接对整个构建过程起作用。 plugins 可用于执行范畴更广的工作,如打包优化、资源管理和从新定义环境中的变量等。 plugins 的根本配置webpack 的配置项中提供了一个 plugins 属性来进行插件的相干配置,该属性的属性值为数组: module.exports = { // loaders plugins: []}webpack 中所有须要用到的 plugin,都在该数组中顺次进行配置。 HtmlWebpackPlugin这里咱们以一个简略的 HtmlWebpackPlugin 插件为例,来学习 webpack 中 plugin 的应用。 HtmlWebpackPlugin 插件的作用次要有两个: 创立生成 html 入口文件;为 html 文件引入的内部资源,如 CSS、JavaScript;根本应用HtmlWebpackPlugin 插件的根本作用就是生成 html 文件,同时能够将 webpack 配置文件中 entry 对应的 js 文件插入到 html 中。 const HtmlWebpackPlugin = require('html-webpack-plugin');module.exports = { plugins: [ new HtmlWebpackPlugin() ]}实例化该插件时能够不应用任何参数,当然也能够传一个对象作为参数,通过具体的配置项来定制化一些非凡的需要。 ...

December 20, 2020 · 1 min · jiezi

关于webpack:webpack5升级指南踩坑记录

CssDependency 报错:No template for dependency: CssDependency问题要害:webpack开发模式不能应用 MiniCssExtractPlugin.loader 解题思路: MiniCssExtractPlugin.loader是用来提取css款式到css文件中并压缩,然而开发环境启动webpack devServer援用的文件都不是打包在dist目录的,是打包到内存中援用的,所以提取的css没有文件来包容它,就会报这个谬误。 报错:[object Object] is not a PostCSS plugin问题要害: 很大可能是我的项目没有装置postcss解题思路: npm i postcss -D报错: NormalModuleFactory.afterResolve is no longer a waterfall hook, but a bailing hook instead. Do not return the passed object, but modify it instead. Returning false will ignore the request and results in no module created问题要害: lodash按需加载插件作者并未降级解题思路: 降级webpack5后,lodash按需加载的babel插件( babel-plugin-lodash, lodash-webpack-plugin)并没有降级,我目前的计划是改为引入lodash es6版本的,通过webpack5更新后更为强悍的treeShaking来按需加载lodash npm i lodash-es -Simport {cloneDeep} from "lodash-es"cloneDeep({a:1,b:2})Error: Cannot find module 'webpack-cli/bin/config-yargs' ...

December 16, 2020 · 1 min · jiezi

关于webpack:升级webpack5热更新失效问题

参考:webpack 踩坑 在练习自定义webpack配置,应用的是webpack5.x版本,而后发现热更新生效。搜寻一番后,从下面的链接失去了解决办法:把package.json里的browserlist去掉。。。 // package.json{// ...- "browserslist": {- "production": [- ">0.2%",- "not dead",- "not op_mini all"- ],- "development": [- "last 1 chrome version",- "last 1 firefox version",- "last 1 safari version"- ]- }}并且,启动我的项目的时候用"serve": "webpack-dev-server --config build/webpack.dev.js"是不行的了,webpack5要换成这样: - "serve": "webpack-dev-server --config build/webpack.dev.js+ "serve": "webpack serve --config build/webpack.dev.js

December 16, 2020 · 1 min · jiezi

关于webpack:webpack项目如何正确打包引入的自定义字体

一. 如何在Vue或React我的项目中应用自定义字体在开发前端我的项目时,常常会遇到UI共事心愿在我的项目中应用一个炫酷字体的需要。那么怎么在我的项目中应用自定义字体呢?其实实现起来并不简单,能够借用CSS3 @font-face 来实现。 本文着重介绍一下 webpack 我的项目如何正确打包引入的自定义字体。 @font-face有什么用总结一下就是:用户借助该规定,能够为引入的字体包命一个名字,并指定在哪里能够找到它(指定字体包的存储门路)后,就能够像应用通用字体那样去应用它了。 具体实现步骤例如当初的需要是:须要在我的项目中应用 KlavikaMedium-Italic 字体。 则只需以下三个步骤即可。 1. 将字体包放入我的项目目录下这里放到根目录下的 tool/fonts 文件夹里。 2. 在index.css文件中定义@font-face { font-family: 'myFont'; src: url(tool/fonts/KlavikaMedium-Italic.otf);}3. 应用自定义字体新建一个index.vue文件,引入款式: import './index.css'<template><h1>应用自定义字体</h1><style> h1 { font-family: 'myFont' }</style></template>成果如下: 二. webpack我的项目如何正确打包自定义的字体1. 打包时报错既然在本地开发环境实现了成果,于是就应用 webpack 打包筹备上线,却发现 webpack 在打包过程中报错: 2. 打包时为什么会报错咱们在定义自定义字体时应用URL指定了字体包的门路,因为 webpack 默认是无奈解决 css 中的 url 地址的,因而这里会报错。 3. 解决报错3.1 意识file-loader这时就须要借助 loader 来大显神通了,解决这个问题须要应用 file-loader,它次要干了两件事儿: 依据配置批改打包后图片、字体包的寄存门路;再依据配置批改咱们援用的门路,使之对应引入。3.2 装置file-loaderyarn add file-loader 3.3 配置file-loader在 webpack.config.js 中,配置file-loader: module.exports = { module: { rules: [ { // 命中字体包 test: /.(woff2?|eot|ttf|otf)(?.*)?$/, // 只命中指定 目录下的文件,放慢Webpack 搜寻速度 include: [paths.toolSrc], // 排除 node_modules 目录下的文件 exclude: /(node_modules)/, loader: 'file-loader', }, ] }}再次执行打包命令,不再报错。 ...

December 9, 2020 · 2 min · jiezi

关于webpack:webpack4配置优化

后面咱们说了webpack的一些根底,当初咱们来应用webpack理论来编译写个我的项目。用vue-cli创立一个我的项目,而后把它的vue-cli-service以及webpack等黑盒工具移除,而后咱们来本人编译它。首先咱们要创立三个文件 webpack.common.js 公共的webpack配置webpack.dev.js 开发阶段的配置webpack.prod.js 生产阶段的配置首先咱们来编写webpack.common文件 const HtmlWebpackPlugin = require('html-webpack-plugin')// html模板const webpack = require('webpack')const PreloadWebpackPlugin = require('preload-webpack-plugin')// 预加载const path = require('path')const os = require('os')const VueLoaderPlugin = require('vue-loader/lib/plugin')// vue对应插件const workers = { // 多线程编译 loader: 'thread-loader', options: { workers: os.cpus().length }}module.exports = { // entry: ['babel-polyfill', './src/main.js'], entry: './src/main.js', // 入口 output: { filename: 'bundle.js' // 输入 }, optimization: { concatenateModules: true, // 尽可能合并模块到一个函数 splitChunks: { // 公共代码拆分 // include all types of chunks chunks: 'all' }, runtimeChunk: true // 运行时代码 拆出来 缓存 }, resolve: { // modules: [//解析时搜寻得模块,配了导致ie报错 // path.resolve(__dirname, 'node_modules'), // ], alias: { // 配置别名 components: path.resolve(__dirname, 'src/components'), src: path.resolve(__dirname, 'src') }, extensions: ['.js', '.json', '.vue'] // 省略后缀 }, module: { rules: [ { // babel test: /\.js$/, exclude: /node_modules/, use: [ workers, { loader: 'babel-loader', options: { // babel-polyfill按需引入,差了1m左右 core polyfill原型 presets: [['@babel/preset-env', { useBuiltIns: 'usage', corejs: 3 }]], cacheDirectory: true, // 开启缓存 第二次构建时,会读取之前的缓存,吃内存,不开发了记得清下占用 // presets: ['@babel/preset-env'] plugins: [ // import()语法反对 '@babel/plugin-syntax-dynamic-import' ] } } ] }, { test: /\.(gif|png|jpe?g|svg)$/i, // 不超过10kb转为data:urlbase64 use: [ { loader: 'url-loader', options: { limit: 10 * 1024, // 10 KB name: 'image/[name]-[contenthash:8].[ext]', // 输入hash esModule: false } }] }, { test: /\.vue$/, // 解析vue文件 use: [ workers, 'vue-loader' ] } ] }, plugins: [ new PreloadWebpackPlugin({ // 退出预解析和预加载webpack4之后下载preload-webpack-plugin@next最新版 rel: 'preload', as (entry) { console.log(entry) if (/\.css$/.test(entry)) return 'style' if (/\.woff$/.test(entry)) return 'font' if (/\.(png|jpe?g|gif)$/.test(entry)) return 'image' return 'script' }, include: 'allChunks', fileBlacklist: [/\.(map)$/, /runtime~.+\.js$/] // 把runtime文件抽离进去,因为import()运行时文件变动了,runtime治理运行时babel导入文件的hash也会变动, // 默认webpack打包进去的依赖入口文件会把runtime导入,这样会导致它的hash也会变动,这样就会导致缓存生效, // 所以把runtime这个文件加载到html中,从以来入口文件中抽离,来防止依赖入口的hash变动。这样它就不须要进行预加载了。 }), new HtmlWebpackPlugin({ // html模板 title: 'Vue dev App', template: path.resolve(__dirname, 'public/index.html') }), new VueLoaderPlugin(), new webpack.DefinePlugin({ // 值要求的是一个代码片段 BASE_URL: '"/"' }) ]}代码里都有正文,而后咱们做下思路剖析: ...

December 6, 2020 · 5 min · jiezi

关于webpack:利用-statsjson-定位-nrwlreact-webpack-配置问题

背景团队应用NX这一 monorepo 工具来搭建 React 利用。NX 基于 React 利用在 webpack 打包时增加了url-loader的相干配置。然而共事反馈该url-loader针对局部援用的图片文件不起作用。 定位url-loader 作用url-loader,简而言之,能够将利用中援用到的一些资源文件(例如图片)转换成 base64 的数据格式,而后嵌入到咱们的利用中(例如 HTML 的 img src, css 中的 url 函数),这样便无需针对该资源发动网络申请,节俭申请资源。 以下是url-loader的配置举例: { "test": "/\\.(png|jpe?g|gif|webp)$/", "loader": require.resolve("url-loader"), "options": { "limit": 10000, // 10kB "name": "[name].[hash:7].[ext]" }}上述配置的意思就是针对 10kB 以下大小的一些常见图片格式文件应用url-loader解决,否则应用 fallback loader 解决,url-loader默认的 fallback loader 是file-loader。超过大小的文件会被其解决,相应的 options 会传给file-loader,例如 name,最终解决后的文件名会包含 7 位 hash。 具体针对哪局部文件不起作用?因为 NX 并不是写好 webpack 配置,再应用 webpack 指令进行打包。而是以Angular CLI builder的模式,引入 webpack 并进行代码编写,领有高度定制化,因而一开始并没有细看其 builder 的源码,很难找到具体是什么文件不起作用,而哪局部又没有问题。 一开始共事与之前的一个利用比照,发现其打包的一部分图片产物被file-loader解决,没有最终文件;而一部分则有最终文件,然而 hash 位数为默认的 20 位而不是file-loader解决后的 7 位;最初一部分文件则位数正确。 ...

December 6, 2020 · 6 min · jiezi