代码构建与webpack知识点
1、Webpack 工具都做了些什么
- 如今前端项目大多数都使用了模块化,而如果想要将多个文件的代码打包成最终可按照预期运行的代码,则需要使用到代码构建工具。
- 不管项目代码是如何进行组织的,项目中又有多少个文件,最终浏览器依然会从 HTML 内容进行解析和加载,因此我们需要对项目中的代码进行构建(包括编译和打包),生成浏览器可正常解析和加载的内容
2、常见的前端构建工具
对于前端开发来说,我们会用到各式各样的构建/打包工具:
涉及模块化代码打包的主要有 Grunt/Gulp/Webpack/Rollup
-
Gulp/Grunt 是一种能够优化前端工作流程的工具,比如自动刷新页面、combo、压缩 CSS/JavaScript、编译 Less/Sass 等
-
Webpack/Rollup 是一个 JavaScript 的模块打包器,用于整合编译成最终的代码。
-
其中,Rollup 通常用来构建库,Webpack 更适合用来构建应用程序。
3、了解Webpack
Webpack 的使用中有 4 个核心概念:入口(entry)、输出(output)、Loader、插件(plugins)
(1)入口(entry)
首先便是入口(entry),entry 指向我们前端应用的第一个启动文件。例如,在 Vue 中是new Vue()位置所在的文件,在 Angular 中是启动.bootstrap()的文件,在 React 中则是ReactDOM.render()或者是React.render()的启动文件。
// 将entry指向启动文件即可
module.exports = {
entry: "./path/to/my/entry/file.js",
};
或许你会疑惑,入口的一个文件,又是怎样把整个前端项目中的代码关联起来,并进行打包的呢?
实际上, Webpack 会从 entry 开始,通过解析模块间的依赖关系,递归地构建出一个依赖图
(2)输出(output)
输出(output)字段用于告诉 Webpack 要将打包后的代码生成的文件名是什么(filename),以及将它们放在哪里(path)。## 入口(entry)
module.exports = {
output: {
filename: "bundle.js", // 编译文件的文件名,比如 main.js/bundle.js/index.js
path: "/home/proj/public/assets", // 对应一个绝对路径,此路径是你希望一次性打包的目录
},
};
(3)Loader
- 要了解 Loader,你需要知道在 Webpack 中,每个文件(.css,.html,.scss,.jpg等) 都会被作为模块处理。如果你看过生成的 bundle.js 代码就会发现,Webpack 将所有的模块打包一起,每个模块添加标记id,通过这样一个 id 去获取所需模块的代码。
- 但实际上,Webpack 只理解 JavaScript,因此 Loader 的作用就是把不同的模块和文件(比如 HTML、CSS、JSX、Typescript 等)转换为 JavaScript 模块。
- 而不同的应用场景需要不同的 Loader,比如我们经常会使用到的 CSS 相关 Loader 和其他资源 Loader。
深度理解:
- ES6 模块需要依赖 Babel 编译和 Webpack 打包,而 Babel 在 Webpack 中就是使用 Loader 的方式来进行编译的。
- babel-loader 将 ES6/ES7 语法编译生成 ES5,其中部分特性还需要 babel-polyfill 支持。这是因为 Babel 默认只转换新的 JavaScript 语法(比如const/let),但不会对新的 API(比如Promise)进行处理。
- Webpack 在编译过程中,支持多个 Loader 通过流水线的方式进行先后编译,编译的顺序为从后往前,最终以 JavaScript模块的方式输出。
- 到这里,我们知道 Webpack 以 entry 为入口,链式调用各个 Loader 进行编译生成 JavaScript,最终打包放置在output 中。其中 Loader 只负责将其他非 JavaScript 模块转换成 JavaScript 模块。
(4)插件(plugins)
插件(plugins)主要负责解决 Loader 无法做到的事情,它可以访问在 Webpack 编译过程中的关键事件,对 Webpack 内部示例的一些数据进行处理,处理完成后回调 Webpack 让其继续。
这样说或许有些抽象,我们直接来看看几个常用的插件就明白了。
- HtmlwebpackPlugin:可以生成创建 HTML 入口文件,也可以为 HTML 文件中引入的外部资源如 script、link 动态添加每次编译后的哈希值,防止引用缓存的外部文件问题。
- CommonsChunkPlugin:用来提取代码中的公共模块,并将这些公共模块按照预期进行打包生成独立的文件。
- ProvidePlugin:用来定义标识符,当遇到指定标识符的时候自动加载模块,适合引入的全局变量(比如 jQuery)。
- ExtractTextPlugin:可以将样式从 JavaScript 中抽出,生成单独的 .css 样式文件。
总结
webpack的插件是可以用来控制最终生成的代码是如何进行组织和输出的,包括对代码的打包优化、压缩,甚至是启用模块热替换、重新定义环境中的变量,等等。
Webpack 到底对项目代码做了什么?
(1) 通过 entry 指定的入口开始,解析各个文件模块间的依赖。
(2)根据模块间的依赖关系,开始对各个模块进行编译。
(3)编译过程中,根据配置的规则对一些模块使用 Loader 进行编译处理。
(4)根据插件的配置,对 Loader 编译后的代码进行封装、优化、分块、压缩等。
(5)最终 Webpack 整合各个模块,根据依赖关系将它们打包成最终的一个或者多个文件。
最终让前端项目中模块化的代码能最终在浏览器中进行加载、并正常地工作。