1、有哪些常见的Loader?他们是解决什么问题的?
- file-loader:把文件输出到一个文件夹中,在代码中通过相对 URL 去引用输出的文件
- url-loader:和 file-loader 类似,但是能在文件很小的情况下以 base64 的方式把文件内容注入到代码中
- source-map-loader:加载额外的 Source Map 文件,以方便断点测试
- image-loader:加载并且压缩图片文件
- babel-loader:把es6 转换成 es5
- css-loader:加载 css,支持模块化、压缩、文件导入等特性
- style-loader:把 css 代码注入到 JavaScrip t中,通过 dom 操作去加载 css
- eslint-loader:通过ESLint 检查 JavaScript 代码
2、有哪些常见的Plugin?他们是解决什么问题的?**
- define-plugin:定义环境变量
- commons-chunk-plugin:提供公共代码
- uglify-webpack-plugin:通过 Uglify 压缩 ES6 代码
3、Loader和Plugin的不同?**
- 不同作用
- loader 只译为’加载器’,webpack将一切文件视为模块,但是webpack原生是只能解析 js文件,如果将其他文件也打包的话,就会用到loader。所以loader的作用是让webpack拥有了加载和解析非JavaScript文件的能力
- plugin 翻译为’插件’,plugin 可以拓展webpack 的功能,让webpack 具有更多的灵活性。让webpack运行的生命周期中广播出许多事件,plugin可以监听这些事件,在合适的时机通过webpack提供的api改变输出结果。
- 不同的用法
- loader 在module.rules中配置,也就是说他作为模块的解析规则而存在,类型为数组,每一项都是一个object,里面描述了对于什么类型的文件(test),使用什么加载(loader)和使用的参数(options)。
- plugin在plugins中单独配置。类型为数组,每一项都是plugin的实例,参数都是通过构造函数传入。
4、webpack的构造流程是什么?**
- webpack的运行流程是一个串行的过程,从启动到结束会依次执行以下流程:
- 初始化参数:从配置文件和Shell 语句中读取与合并参数,得出最终的参数;
- 开始编译:用上一步得到的参数初始化compiler对象,加载所有配置的插件,执行对象的run方法开始执行编译;
- 确定入口:从入口文件触发,调用所有配置的loader对模块进行编译,再找出该模块依赖的模块,在递归本步骤直接到所有入口依赖的文件都经过了本步骤的处理;
- 完成模块编译:在经过第4步使用loader翻译完所有模块后,得到了每个模块被翻译后的最终内容以及他们之间的依赖关系;
- 输出资源:根据入口和模块之间的依赖关系,组装成一个个包含多个模块的Chunk,再把chunk转换为一个单独的文件加入到输出列表,这步可以修改输出内容的最后机会;
- 输出完成:在确定好输出的内容后,根据配置确定输出路径和文件名,把文件内容写到文件系统。
- 在以上过程中,webpack会在特定时间点广播特定的事件,插件在监听到感兴趣的事件后执行特定的逻辑,并且插件可以调用webpack提供的api改变webpack的运行结果。
5、webpack的热更新**
- webpack的热更新又称热替换(Hot Module Replacement),缩写为HMR。这个机制可以做到不用刷新浏览器而将新变更的模块替换掉旧的模块。
- 原理:
- 1、在webpack的watch模式下,文件系统中某一个文件发生修改,webpack监听到文件变化,根据配置文件对模块重新编译打包,并将打包后的代码通过简单的 JavaScript 对象保存在内存中。
- 2、webpack-dev-server和webpack之间的接口交互,而在这一步,主要是dev-server的中间件webpack-dev-middleware 和 webpack 之间的交互,webpack-dev-middleware调用webpack 暴露的api对代码变化进行监控,并且告诉 webpack,将代码打包到内存中。
- 3、webpack-dev-server 对文件变化的一个监控,这一步不同于第一步,并不是监控代码变化重新打包。当我们配置文件中配置了devServer.watchContentBase 为 true 的时候Server 会监听这些配置文件夹中静态文件的变化,变化后通知浏览器端对应用进行 live reload。注意,这里是浏览器刷新,和HMR 是两个概念。
- 4、webpack-dev-server 代码的工作,这步骤主要通过 sockjs 在浏览器端和服务端之间建立一个websocket长连接,将 webpack 编译打包的各个阶段的状态信息告知浏览器端,同时也包括第三步中Server监听静态文件变化的信息。浏览器端根据这些socket消息进行不同的操作。当然服务端传递的最主要信息还是新模块的hash值,后面的步骤根据这一hash值来进行模块热替换。
- 5、webpack-dev-server/client 端并不能够请求更新的代码,也不会执行热更模块操作,而把这些工作又交回给了webpack,webpack/hot/dev-server 的工作根据webpack-dev-server-client 传给它的信息以及 dev-server 的配置决定是刷新浏览器还是进行模块热更新。当然如果仅仅是刷新浏览器,也就没有后面那些步骤了。
- 6、HotModuleRrplacement.runtime 是客户端 HMR 中枢,他接受到上一步传递给他的新模块的hash值,他通过 jsonpMainTemplate.runtime 向 server 端发送Ajax请求,服务端返回一个 json,该 json 包含了所有要更新的模块的hash值,获取到更新列表后,该模块再次通过 jsonp 请求,获取都最新的模块代码。
- 7、HotModulePlugin 将会对新旧模块进行对比,决定是否更新模块,在决定更新模块后,检查模块之间的依赖关系,更新模块的同时更新模块间的依赖引用。
- 8、当HMR失败后,回退到 live reload 操作,也就是进行浏览器刷新来获取最新打包代码。
6、如何用webpack来优化前端性能**
用webpack优化前端性能是指优化webpack的输出结果,让打包的最终结果在浏览器运行快速高效。
- 压缩代码。删除多余的代码、注释、简化代码的写法等等方式。可以利用webpack的UglifyJsPlugin和ParallelUglifyPlugin来压缩JS文件, 利用cssnano(css-loader?minimize)来压缩css
- 利用CDN加速。在构建过程中,将引用的静态资源路径修改为CDN上对应的路径。可以利用webpack对于output参数和各loader的publicPath参数来修改资源路径
- 删除死代码(Tree Shaking)。将代码中永远不会走到的片段删除掉。可以通过在启动webpack时追加参数—optimize-minimize来实现
- 提取公共代码。
- 压缩代码。删除多余的代码、注释、简化代码的写法等等方式。可以利用webpack的UglifyJsPlugin和ParallelUglifyPlugin来压缩JS文件, 利用cssnano(css-loader?minimize)来压缩css
7、怎么配置单页应用?怎么配置多页应用?
单页应用可以理解为webpack的标准模式,直接在entry中指定单页应用的入口即可,这里不再赘述
多页应用的话,可以使用webpack的 AutoWebPlugin来完成简单自动化的构建,但是前提是项目的目录结构必须遵守他预设的规范。 多页应用中要注意的是:**
- 每个页面都有公共的代码,可以将这些代码抽离出来,避免重复的加载。比如,每个页面都引用了同一套css样式表
- 随着业务的不断扩展,页面可能会不断的追加,所以一定要让入口的配置足够灵活,避免每次添加新页面还需要修改构建配置
8、npm打包时需要注意哪些?如何利用webpack来更好的构建?
Npm是目前最大的 JavaScript 模块仓库,里面有来自全世界开发者上传的可复用模块。你可能只是JS模块的使用者,但是有些情况你也会去选择上传自己开发的模块。 关于NPM模块上传的方法可以去官网上进行学习,这里只讲解如何利用webpack来构建。**
NPM模块需要注意以下问题:
要支持CommonJS模块化规范,所以要求打包后的最后结果也遵守该规则。 Npm模块使用者的环境是不确定的,很有可能并不支持ES6,所以打包的最后结果应该是采用ES5编写的。并且如果ES5是经过转换的,请最好连同SourceMap一同上传。
Npm包大小应该是尽量小(有些仓库会限制包大小) 发布的模块不能将依赖的模块也一同打包,应该让用户选择性的去自行安装。这样可以避免模块应用者再次打包时出现底层模块被重复打包的情况。
UI组件类的模块应该将依赖的其它资源文件,例如.css文件也需要包含在发布的模块里。
基于以上需要注意的问题,我们可以对于webpack配置做以下扩展和优化:
CommonJS模块化规范的解决方案:
设置output.libraryTarget=’commonjs2’使输出的代码符合CommonJS2 模块化规范,以供给其它模块导入使用
输出ES5代码的解决方案:使用babel-loader把 ES6 代码转换成 ES5 的代码。再通过开启devtool: ‘source-map’输出SourceMap以发布调试。
Npm包大小尽量小的解决方案:Babel 在把 ES6 代码转换成 ES5 代码时会注入一些辅助函数,最终导致每个输出的文件中都包含这段辅助函数的代码,造成了代码的冗余。解决方法是修改.babelrc文件,为其加入transform-runtime插件
不能将依赖模块打包到NPM模块中的解决方案:使用externals配置项来告诉webpack哪些模块不需要打包。
对于依赖的资源文件打包的解决方案:通过css-loader和extract-text-webpack-plugin来实现
9、Feach 与 axios 的区别?
fetch**
- 优点
- 更加底层、提供的API丰富(request、response)
- 脱离了XHR,是ES规范里新的实现方式
- 缺点
- fetch只对网络请求报错,对400,500都当做成功的请求,需要封装去处理
- fetch 默认不会带 cookie,需要添加配置项
- fetch 不支持 abort,不支持超时控制,使用 setTimeout 及 Promise.reject 的实现的超时控制并不能阻止请求过程继续在后台运行,造成了流量的浪费
- fetch 没有办法原生监测请求的进度,而XHR可以
axios 特点:
- 从浏览器中创建XMLHttpRequest
- 从node.js 发出 http 请求
- 支持 Promise API
- 拦截请求和相应
- 转换请求和响应数据
- 取消请求
- 自动转换JSON数据
- 客户端支持防止CSRF/XSRF
