-
- 1、webpack是什么?
- 2、webpack与grunt、gulp的区别?
-
- 2.1、区别
- 2.2、总结
- 3、Webpack的五个核心概念
- 4、有哪些常见的Loader?你用过哪些Loader?
- 5、有哪些常见的Plugin?你用过哪些Plugin?
- 6、Loader和Plugin的区别?
- 7、怎么配置单页应用?
- 8、怎么配置多页应用?
- 9、使用webpack开发时,你用过哪些可以提高效率的插件?
- 10、Webpack构建流程简单说一下
- 11、babel的原理
- 12、代码分割的本质是什么?有什么意义呢?
- 13、在实际工程中,配置文件上百行乃是常事,如何保证各个loader按照预想方式工作?
- 14、文件指纹是什么?怎么设置?
-
- 14.1、文件指纹
- 14.2、设置
- 15、如何对bundle体积进行监控和分析?
- 16、模块打包的原理
1、一种前端资源构建工具,一个静态模块打包器(nodule bundle)。 2、前端所有资源文件(js/json/css/img…)都会作为模块处理。 3、它将根据模块的依赖关系进行静态分析,打包生成对应的静态资源(bundle)。
2、webpack与grunt、gulp的区别? 2.1、区别1、grunt和gulp是基于任务流(Task、Stream)的。类似jQuery,找到一个(或一类)文件,对其做一系列链式操作,整条链式操作构成了一个任务,多个任务就构成了整个web的构建流程。 2、webpack是基于入口的。webpack会自动地递归解析入口所需要加载的所有资源文件,然后用不同的Loader来处理不同的文件,用Plugin来扩展webpack功能。
2.2、总结从构建思路来说
gulp和grunt需要开发者将整个前端构建过程拆分成多个Task,并合理控制所有Task的调用关系。webpack需要开发者找到入口,并需要清楚对于不同的资源应该使用什么Loader做何种解析和加工。
从知识背景来说
gulp更像后端开发者的思路,需要对于整个流程了如指掌webpack更倾向于前端开发者的思路。
3、Webpack的五个核心概念1、Entry:入口指示Webpack以哪个文件为入口起点开始打包,分析内部构件依赖图。 2、Output:输出指示Webpack打包后的资源bundles输出到哪里去,以及如何命名。 3、Loader:能让Webpack处理非JavaScript/json文件(Webpack自身只能处理JavaScript/json )。 4、Plugins:插件可以用于执行范围更广的任务,包括从打包优化和压缩到重新定义环境中的变量。 5、Mode:模式指示Webpack使用相应模式的配置,只有development(开发环境)和production(生产环境)两种模式。
4、有哪些常见的Loader?你用过哪些Loader?1、raw-loader:加载文件原始内容(utf-8)。 2、file-loader:把文件输出到一个文件夹中,在代码中通过相对URL去引用输出的文件(处理图片和字体)。 3、url-loader:与file-loader类似,区别是用户可以设置一个阈值,大于阈值会交给file-loader处理,小于阈值时返回文件base64形式编码(处理图片和字体)。 4、source-map-loader:加载额外的Source Map文件,以方便断点调试。 5、svg-inline-loader:将压缩后的SVG内容注入代码中。 7、image-loader:加载并且压缩图片文件。 8、json-loader:加载JSON文件(默认包含)。 9、handlebars-loader:将Handlebars模版编译成函数并返回。 10、babel-loader:把ES6转换成ES5。 11、ts-loader:将TypeScript转换成JavaScript。 12、awesome-typescript-loader:将TypeScript转换成JavaScript,性能优于ts-loader。 13、sass-loader:将SCSS/SASS代码转换成CSS。 14、css-loader:加载CSS,支持模块化、压缩、文件导入等特性。 15、style-loader:把CSS代码注入到JavaScript中,通过DOM操作去加载CSS。 16、postcss-loader:扩展CSS语法,使用下一代CSS,可以配合autoprefixer插件自动补齐CSS3前缀。 17、eslint-loader:通过ESLint检查JavaScript代码。 18、tslint-loader:通过TSLint检查TypeScript代码。 19、mocha-loader:加载Mocha测试用例的代码。 20、coverjs-loader:计算测试的覆盖率。 21、vue-loader:加载Vue.js单文件组件。 22、i18n-loader:国际化。 23、cache-loader:可以在一些性能开销较大的Loader之前添加,目的是将结果缓存到磁盘里。
5、有哪些常见的Plugin?你用过哪些Plugin?1、define-plugin:定义环境变量(Webpack4之后指定mode会自动配置)。 2、ignore-plugin:忽略部分文件。 3、html-webpack-plugin:简化HTML文件创建(依赖于html-loader)。 4、web-webpack-plugin:可方便地为单页应用输出HTML,比html-webpack-plugin好用。 5、uglifyjs-webpack-plugin:不支持ES6压缩(Webpack4以前)。 6、terser-webpack-plugin:支持压缩ES6(Webpack4)。 7、webpack-parallel-uglify-plugin:多进程执行代码压缩,提升构建速度。 8、mini-css-extract-plugin:分离样式文件,CSS提取为独立文件,支持按需加载(替代extract-text-webpack-plugin)。 9、serviceworker-webpack-plugin:为网页应用增加离线缓存功能。 10、clean-webpack-plugin:目录清理。 11、ModuleConcatenationPlugin:开启Scope Hoisting。 12、speed-measure-webpack-plugin:可以看到每个Loader和Plugin执行耗时(整个打包耗时、每个Plugin和Loader耗时)。 13、webpack-bundle-analyzer:可视化Webpack输出文件的体积(业务组件、依赖第三方模块)。
6、Loader和Plugin的区别?1、Loader本质就是一个函数,在该函数中对接收到的内容进行转换,返回转换后的结果。因为Webpack只认识JavaScript,所以Loader就成了翻译官,对其他类型的资源进行转译的预处理工作。 2、Plugin就是插件,基于事件流框架Tapable,插件可以扩展Webpack的功能,在Webpack运行的生命周期中会广播出许多事件,Plugin可以监听这些事件,在合适的时机通过Webpack提供的API改变输出结果。 3、Loader在module.rules中配置,作为模块的解析规则,类型为数组。每一项都是一个Object,内部包含了test(类型文件)、loader、options(参数)等属性。 4、Plugin在plugins中单独配置,类型为数组,每一项是一个Plugin的实例,参数都通过构造函数传入。
7、怎么配置单页应用? 8、怎么配置多页应用? 9、使用webpack开发时,你用过哪些可以提高效率的插件?1、webpack-dashboard:可以更友好的展示相关打包信息。 2、webpack-merge:提取公共配置,减少重复配置代码。 3、speed-measure-webpack-plugin:简称SMP,分析出Webpack打包过程中Loader和Plugin的耗时,有助于找到构建过程中的性能瓶颈。 4、size-plugin:监控资源体积变化,尽早发现问题。 5、HotModuleReplacementPlugin:模块热替换。
10、Webpack构建流程简单说一下Webpack的运行流程是一个串行的过程。
1、初始化参数:从配置文件和Shell语句中读取与合并参数,得出最终的参数。 2、开始编译:用上一步得到的参数初始化Compiler对象,加载所有配置的插件,执行对象的run方法开始执行编译。 3、确定入口:根据配置中的entry找出所有的入口文件。 4、编译模块:从入口文件出发,调用所有配置的Loader对模块进行翻译,再找出该模块依赖的模块,再递归本步骤直到所有入口依赖的文件都经过了本步骤的处理。 5、完成模块编译:在经过第4步使用Loader翻译完所有模块后,得到了每个模块被翻译后的最终内容以及它们之间的依赖关系。 6、输出资源:根据入口和模块之间的依赖关系,组装成一个个包含多个模块的Chunk,再把每个Chunk转换成一个单独的文件加入到输出列表,这步是可以修改输出内容的最后机会。 7、输出完成:在确定好输出内容后,根据配置确定输出的路径和文件名,把文件内容写入到文件系统。
在以上过程中,Webpack会在特定的时间点广播出特定的事件,插件在监听到感兴趣的事件后会执行特定的逻辑,并且插件可以调用Webpack提供的API改变Webpack的运行结果。
简单说
1、初始化:启动构建,读取与合并配置参数,加载Plugin,实例化Compiler。 2、编译:从Entry出发,针对每个Module串行调用对应的Loader去翻译文件的内容,再找到该Module依赖的Module,递归地进行编译处理。 3、输出:将编译后的Module组合成Chunk,将Chunk转换成文件,输出到文件系统中。
11、babel的原理1、解析:将代码转换成AST。 1.1、词法分析:将代码(字符串)分割为token流,即语法单元成的数组。 1.2、语法分析:分析token流(上面生成的数组)并生成AST。 2、转换:访问AST的节点进行变换操作生产新的AST。 2.1、Taro就是利用babel完成的小程序语法转换。 3、生成:以新的AST为基础生成代码。
12、代码分割的本质是什么?有什么意义呢?12.1、代码分割的本质其实就是在源代码直接上线和打包成唯一脚本main.bundle.js这两种极端方案之间的一种更适合实际场景的中间状态。
12.2、意义是用可接受的服务器性能压力增加来换取更好的用户体验。
12.3、对比
12.3.1、源代码直接上线:虽然过程可控,但是http请求多,性能开销大。 12.3.2、打包成唯一脚本:一把梭完自己爽,服务器压力小,但是页面空白期长,用户体验不好。
13、在实际工程中,配置文件上百行乃是常事,如何保证各个loader按照预想方式工作?可以使用enforce强制执行loader的作用顺序,pre代表在所有正常loader之前执行,post是所有loader之后执行。(官方不推荐使用inline)
14、文件指纹是什么?怎么设置? 14.1、文件指纹文件指纹是打包后输出的文件名的后缀。
14.1.1、Hash:和整个项目的构建相关,只要项目文件有修改,整个项目构建的hash值就会更改。 14.1.2、Chunkhash:和Webpack打包的chunk有关,不同的entry会生出不同的chunkhash。 14.1.3、Contenthash:根据文件内容来定义hash,文件内容不变,则contenthash不变。
14.2、设置14.2.1、JS的文件指纹设置
设置output的filename,用chunkhash。
module.exports = { entry: { app: './scr/app.js', search: './src/search.js' }, output: { filename: '[name][chunkhash:8].js', path: __dirname + '/dist' } };
14.2.2、CSS的文件指纹设置
设置MiniCssExtractPlugin的filename,使用contenthash。
module.exports = { entry: { app: './scr/app.js', search: './src/search.js' }, output: { filename: '[name][chunkhash:8].js', path: __dirname + '/dist' }, plugins: [ new MiniCssExtractPlugin({ filename: `[name][contenthash:8].css` }) ] };
14.2.3、图片的文件指纹设置
设置file-loader的name,使用hash。
占位符名称及含义
1、ext资源后缀名。 2、name文件名称。 3、path文件的相对路径。 4、folder文件所在的文件夹。 5、contenthash文件的内容hash,默认是md5生成。 6、hash文件内容的hash,默认是md5生成。 7、emoji一个随机的指代文件内容的emoj。
const path = require('path'); module.exports = { entry: './src/index.js', output: { filename: 'bundle.js', path: path.resolve(__dirname, 'dist') }, module: { rules: [ { test: /\.(png|svg|jpg|gif)$/, use: [ { loader: 'file-loader', options: { name: 'img/[name][hash:8].[ext]' } } ] } ] } };15、如何对bundle体积进行监控和分析?
1、VSCode中有一个插件Import Cost可以对引入模块的大小进行实时监测,还可以使用webpack-bundle-analyzer生成bundle的模块组成图来显示所占体积。 2、bundlesize工具包可以进行自动化资源体积监控。
16、模块打包的原理Webpack实际上为每个模块创造了一个可以导出和导入的环境,本质上并没有修改代码的执行逻辑,代码执行顺序与模块加载顺序也完全一致。