一、前端工程化
前端工程化是把前端开发工作带入到更加系统和规范体系的一系列过程,这个过程包括源代码的预编译、模块处理、代码压缩等构建方面的工作。工程化会进尽可能保证开发者的开发体验更友好,保证源代码的质量以及依赖的完整性;工程化也会尽可能高效地将构建完成后的代码送达给客户端,来追求更好的用户体验。
- 对一个工程进行设计并把它拆分成各个组件和模块时,是在做工程化;
- 用Webpack构建项目,配置好各个环境的打包配置时,是在做工程化;
- 为项目添加ESLint并每次提交之前自动检查代码质量时,是在做工程化。
那前端为什么要进行打包和构建呢?
1)打包后可使体积更小(Tree-Shaking、压缩、合并),加载更快;
2)能编译高级语言或语法(TypeScript、ES6+、SCSS、模块化);
3)兼容性和错误检查(Polyfill、postcss、ESLint)
代码打包工具常见的有Gulp、Grunt、Webpack等。不同之处在于Gulp、Grunt属于自动化构建工具,打包思路:遍历源文件-匹配规则-打包,这个过程中做不到按需加载;而Webpack属于静态资源打包工具,是从入口文件开始,经过模块依赖加载、分析和打包三个流程完成项目的构建,在加载、分析和打包的三个过程中可以针对性地做一些解决方案来达到按需加载的目的(如拆分公共代码等)。
webpack 是一个模块打包器(module bundler)(例如,Browserify或Brunch)。它不是一个任务执行器(task runner)(例如,Make,Grunt或者Gulp)。任务执行器就是用来自动化处理常见的开发任务,例如项目的检查(lint)、构建(build)、测试(test)。相对于打包器(bundler),任务执行器则聚焦在偏重上层的问题上面。而打包器(bundler)帮助你取得准备用于部署的 JavaScript 和样式表,将它们转换为适合浏览器的可用格式。例如,JavaScript 可以压缩、拆分 chunk和懒加载,以提高性能。打包是 web 开发中最重要的挑战之一,解决此问题可以消除开发过程中的大部分痛点。
二、Webpack基础
Webpack是可配置的模块打包工具,可以通过修改Webpack的配置文件(webpack.config.js)来对Webpack进行配置。该配置文件遵循Node.js的CommonJS模块规范。
// webpack.config.js示例
const path = require('path');
module.exports = {
mode: 'development',
entry: './foo.js',
output: {
path: path.resolve(__dirname, 'dist'),
filename: 'foo.bundle.js'
}
};
上面示例中,使用 CommonJS 的require
引入 Node.js 内置的path
模块,然后通过module.exports
将 Webpack 的配置导出。
![927a06364574b2960256f32f358a69de.png](https://i-blog.csdnimg.cn/blog_migrate/2669e5965047ce310dab04b7f956aa26.jpeg)
2.1 4个核心概念:entry output loader plugin
entry:项目入口。如果是单页面应用,那么可能入口只有一个;如果是多个页面的项目,那么经常是一个页面会对应一个构建入口。
output:webpack 的output是指定了entry对应文件编译打包后的输出 bundle。常用属性path制定了输出的 bundle 存放的路径,比如dist;filename是 bundle 的名称;publicPath指定了一个在浏览器中被引用的 URL 地址,被用来作为src或者link指向该文件。这种做法在需要将静态文件放在不同的域名或者 CDN 上面的时候是很有用的。
Webpack 是从指定的入口文件(entry)开始,经过加工处理,最终按输出output设定输出固定内容的 bundle;而这个加工处理的过程,就用到了loader和plugin两个工具——使用 loader 处理多种代码语言的转换,使用 plugin 扩展原有的模块打包流程:
1)loader模块转换器:源代码的处理器,loader面向的是解决某个或者某类模块的问题,通过loader可以做一些跟文件自身属性相关的一些操作;(Webpack 本身只能处理 JavaScript,而对于别的类型的语法则完全不认识。loader 可以被理解成对于 Webpack 能力的扩展。如果我们需要引入某一类型的模块,那么就需要通过为它添加特性类型的 loader。)loader让 webpack 能够去处理那些非 JavaScript 文件(webpack 自身只理解 JavaScript)。loader 可以将所有类型的文件转换为 webpack 能够处理的有效模块,然后你就可以利用 webpack 的打包能力,对它们进行处理。
2)plugin扩展插件: 面向的是项目整体,解决的是loader处理不了的事情。想要使用一个插件,你只需要require()它,然后把它添加到plugins数组中。
如模块转换器less-loader是将less转换为css,而扩展插件HtmlWebpackPlugin是一个可以将js和css塞进html文件里的插件。
2.2 3个重要概念:module chunks bundle
module-各个源码文件即通过import、require语句引入的代码,也包括CSS、图片等资源;
chunk-多模块合并成的,chunk是webpack根据功能拆分出来的,chunk包含着module,可能是一对多也可能是一对一。chunk包含如entry、 import()、 splitChunk三种实现代码拆分的情况;
bundle-最终的输出文件。bundle是webpack打包之后的各个文件,一般就是和chunk(代码块)是一对一的关系,bundle就是对chunk进行编译压缩打包等处理之后的产出。
2.3 Webpack基本使用:解析ES6、解析样式、解析图片文件。
解析ES6+主要是Babel,具体使用介绍参见:使用Babel转换JavasCript代码;
解析样式相关loader主要分预处理器和后处理器loader,参见:webpack基础配置-css样式相关loader;
解析图片文件主要loader有url-loader、file-loader、image-webpack-loader等,参见:webpack基础配置-管理项目中的静态资源
2.4 通常把webpack的配置文件拆分成base通用、dev开发环境、prod生产环境三个不同的配置文件(为复用和区分利于模块化)。区分开发和生产环境两套配置,各司其职,例如在开发阶段,代码压缩、压缩图片、计算 hash、提取 CSS 这些都没有必要做。而开发环境需要生成 sourcemap 文件、打印 debug 信息、hot reload 的功能。
我们可以把 webpack 的配置按照不同的环境拆分成多个文件,运行时直接根据环境变量加载对应的配置即可。基本的划分如下:
- webpack.base.js:基础部分,即多个文件中共享的配置
- webpack.development.js:开发环境使用的配置
- webpack.production.js:生产环境使用的配置
- webpack.test.js:测试环境使用的配置
三、Webpack高级
webpack代码拆分方式
拆分文件是为了更好地利用缓存,分离公共类库很大程度上是为了让多页面利用缓存,从而减少下载的代码量,同时,也有代码变更时可以利用缓存减少下载代码量的好处。
在 Webpack 中,总共提供了三种方式来实现代码拆分(Code Splitting):
- entry 配置:通过多个 entry 文件来实现;
- 动态加载(按需加载):通过写代码时主动使用import()或者require.ensure来动态加载;
- 抽取公共代码:使用splitChunks配置来抽取公共代码。
webpack优化构建速度——提高开发体验和效率
可用于生产环境:
1)优化babel-loader;
2)IgnorePlugin;
3)noParse;
4)happyPack;
5)ParalleUglifyPlugin;
不用于生产环境,用于开发环境:
1)自动刷新;
2)热更新;
3)DllPlugin
webpack优化产出代码——提升产品性能
1)小图片base64编码;
2)bundle加hash;
3)懒加载;
4)提取公共代码;
5)使用CDN加速;
6)IgnorePlugin;
7)使用Production模式默认开启tree-shaking;
8)Scope Hosting;
本文引用参考:
05 基础概念和常见配置项介绍(一)-慕课专栏www.imooc.com 19 使用 Webpack 的 splitChunks 功能来拆分代码-慕课专栏www.imooc.com 12 使用 Webpack 管理项目中的静态资源-慕课专栏www.imooc.com Webpack 前端工程化入门GITBOOK.CNgitbook.cn![5b75eb371084187d8f0b26c0a166eb84.png](https://i-blog.csdnimg.cn/blog_migrate/d2a1826e463f0c6c933747d5221ea787.jpeg)