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 来实现
什么是 loader ? 什么是 plugin ?
【Loader】:用于对模块源码的转换,loader 描述了 webpack 如何处理非 javascript 模块,并且在 buld 中引入这些依赖。loader 可以将文件从不同的语言(如 TypeScript)转换为 JavaScript,或者将内联图像转换为 data URL。比如说:CSS-Loader,Style-Loader 等。
【Plugin】:目的在于解决 loader 无法实现的其他事,从打包优化和压缩,到重新定义环境变量,功能强大到可以用来处理各种各样的任务。webpack 提供了很多开箱即用的插件:CommonChunkPlugin 主要用于提取第三方库和公共模块,避免首屏加载的 bundle 文件,或者按需加载的 bundle 文件体积过大,导致加载时间过长,是一把优化的利器。而在多页面应用中,更是能够为每个页面间的应用程序共享代码创建 bundle。
loader:模块转换器,webpack
将一切文件视为模块,但 webpack
只能解析 JavaScript
文件,而 loader 作用是让 webpack
拥有了加载 和 解析非 JavaScript
文件的能力。
plugin:在 webpack
构建流程中的特定时机注入扩展逻辑,让它具有更多的灵活性。在 webpack
运行的生命周期中会广播出许多事件,plugin
可以监听这些事件,在合适的时机通过 webpack
提供的 API 改变输出结果。
用法的区别:
Loader
在 module.rules
中配置,也就是说他作为模块的解析规则而存在。 类型为数组,每一项都是一个 Object,里面描述了对于什么类型的文件(test),使用什么加载(loader)和使用的参数(options)Plugin
在 plugins
中单独配置。 类型为数组,每一项是一个 plugin
的实例,参数都通过构造函数传入。
有哪些常见的 Loader ?他们是解决什么问题的?
file-loader
:把文件输出到一个文件夹中,在代码中通过相对 URL 去引用输出的文件url-loader
:和 file-loader 类似,但是能在文件很小的情况下以 base64 的方式把文件内容注入到代码中去source-map-loader
:加载额外的 Source Map 文件,以方便断点调试image-loader
:加载并且压缩图片文件babel-loader
:把 ES6 转换成 ES5css-loader
:加载 CSS,支持模块化、压缩、文件导入等特性style-loader
:把 CSS 代码注入到 JavaScript 中,通过 DOM 操作去加载 CSS。eslint-loader
:通过 ESLint 检查 JavaScript 代码svg-inline-loader
:将压缩后的 SVG 内容注入代码中json-loader
: 加载 JSON 文件(默认包含)ts-loader
: 将 TypeScript 转换成 JavaScriptawesome-typescript-loader
:将 TypeScript 转换成 JavaScript,性能优于 ts-loadersass-loader
:将 CSS 代码注入 JavaScript 中,通过 DOM 操作去加载 CSSpostcss-loader
:扩展 CSS 语法,使用下一代 CSS,可以配合 autoprefixer 插件自动补齐 CSS3 前缀tslint-loader
:通过 TSLint 检查 TypeScript 代码vue-loader
:加载 Vue.js 单文件组件
有哪些常见的 Plugin?他们是解决什么问题的?
define-plugin
:定义环境变量commons-chunk-plugin
:提取公共代码terser-webpack-plugin
: 支持压缩 ES6 (Webpack4)ignore-plugin
:忽略部分文件html-webpack-plugin
:简化 HTML 文件创建 (依赖于 html-loader)web-webpack-plugin
:可方便地为单页应用输出 HTML,比 html-webpack-plugin 好用mini-css-extract-plugin
: 分离样式文件,CSS 提取为独立文件,支持按需加载serviceworker-webpack-plugin
:为网页应用增加离线缓存功能clean-webpack-plugin
: 删除打包文件happypack
:实现多线程加速编译
如何利用 webpack 来优化前端性能?
用 webpack
优化前端性能是指优化 webpack
的输出结果,让打包的最终结果在浏览器运行快速高效。
1.压缩代码。删除多余的代码、注释、简化代码的写法等等方式。
用 UglifyJsPlugin
和ParallelUglifyPlugin
压缩 JS 文件
用 mini-css-extract-plugin
压缩 CSS
- 利用 CDN 加速。在构建过程中,将引用的静态资源路径修改为 CDN 上对应的路径。可以利用
webpack
对于output
参数和各loader
的publicPath
参数来修改资源路径 - 删除死代码。JS 用
Tree Shaking
,CSS 需要使用Purify-CSS
- 提取公共代码。用
CommonsChunkPlugin
插件
分别介绍 bundle,chunk,module 是什么
bundle
:是由 webpack
打包出来的文件,chunk
:代码块,一个 chunk
由多个模块组合而成,用于代码的合并和分割。module
:是开发中的单个模块,在 webpack
的世界,一切皆模块,一个模块对应一个文件,webpack
会从配置的 entry
中递归开始找出所有依赖的模块。