本文编写自26届同学:madMaxxx
前端工程化
什么是前端工程化
前端工程化,就是降本提效的体现
广义上,前端工程化包含一切以降低成本、提高效率、保障质量为目的的手段
通过一系列的规范、流程、工具达到研发提效、自动化、保障质量、服务稳定、预警监控等
一个优秀的前端工程师,需要对所开发项目的效率、性能、质量等工程化维度,去制定和实施技术优化指标,只有具备这方面能力,才能应对和优化复杂项目,保证团队高效产出
前端构建工具
简单来说,构建工具是可以帮助开发者管理本地源文件,优化开发流程,降低开发复杂度,使开发者更加专注在业务逻辑开发上的一种工具。我们在开发环境的代码,是为了方便阅读与开发,生产环境的代码则是为了代码更好的运行。开发环境的代码,要进行压缩编译以后,才能放在线上执行,这样代码体积更小,加载起来更快,所以构建工具一般有以下几种作用:
- 代码压缩
将js、css代码混淆压缩,让代码体积更小,加载更快
- 编译语法
编写css时使用Less、Scss,编写js时使用es6、ts等,这些标准目前都无法被浏览器兼容,因此需要构建工具编译,例如使用Babel编译es6语法。
- 处理模块化
css和js的模块化语法,目前都无法被浏览器兼容。因此开发环境可以使用既定的模块化语法,但是需要构建工具将模块化语法编译为浏览器可识别形式。例如使用webpack、Rollup等处理js模块化。
市面上的构建工具特别多:
- webpack
- vite
- rollup
- esbuild
- parcel
- gulp
- ......
课件主要介绍webpack和vite
webpack
webpack是一个现代 JavaScript 应用程序的静态资源打包工具。静态资源包括html、css、js,图片、字体等文件。webpack会以一个或多个文件作为打包入口,将整个项目所有文件编译组合成一个或多个文件输出,输出的文件就是编译好的文件,我们把它叫做bundle。
如何使用webpack进行打包
webpack简单使用
创建项目
- 初始化项目npm/yarn init -y并生成 package.json,使用npm来管理项目依赖项。
- 安装webpack webpack-cli两个依赖,webpack-cil的作用就是使得可以在命令行中使用webpack,主要代码写在webpack中。
- 创建src目录,添加主文件,一般为index.js
- 启动打包
mkdir webpackdemo
cd webpackdemo npm init -y
npm add -D webpack webpack-cli //D表示webpack为开发环境所需要的依赖
npx webpack
//package.json内容
{
"name": "homeworkpack",//文件名
"version": "1.0.0",
"description": "",
"main": "index.js",//入口文件
"scripts": {
"test": "echo "Error: no test specified" && exit 1"
},
"keywords": [],
"author": "",
"license": "ISC",
"devDependencies": {
"@babel/core": "^7.21.4",
"@babel/preset-env": "^7.21.4",
"babel-loader": "^9.1.2",
"bable-loader": "^0.0.1-security",
"css-loader": "^6.7.3",
"file-loader": "^6.2.0",
"html-loader": "^4.2.0",
"html-webpack-plugin": "^5.5.0",
"mini-css-extract-plugin": "^2.7.5",
"style-loader": "^3.3.2",
"url-loader": "^4.1.1",
"webpack": "^5.79.0",
"webpack-cli": "^5.0.1",
"webpack-dev-server": "^4.13.2"
},
"dependencies": {
"@types/webpack": "^5.28.1"
}
}
webpack配置文件相关
webpack配置文件(webpack.config.js)用于配置webpack是如何运行的,该配置文件是给node.js看的,在写代码是要遵循nodejs的模块化规范。
-
entry
入口告诉webpack应该从哪里开始构建内部依赖图,处理依赖并输出到bundles里。默认是src文件夹下的index.js。
-
output
出口告诉webpack如何输出它构建的bundles,包括路径、命名规则等。默认的输出为根目录dist文件夹。
-
loader
loader相关
webpack在默认情况上只能处理js、json文件,如果希望webpack具备打包其他类型文件的能力,则需要安装依赖,loader可以使webpack识别处理其他文件并转化成模块,不同的loader可以处理不同类型的文件,比如使用style-loader,css-loader使得css文件里的代码转换为js代码,并且可以在js文件里import css文件,以使得浏览器可以直接识别。
loader本质上是一种mapping函数形式,接收原始代码内容,返回翻译结果,如:
module.exports = function(source) { // 执行各种代码计算 return modifySource }安装css-loader:
npm add css-loaer -D -
mode
模式参数,通过选择 development, production 或 none 之中的一个,来设置 mode 参数,你可以启用 webpack 内置在相应环境下的优化。其默认值为 production。 比如在开发环境下,你可以使用source map来清楚的知道你的报错位置在哪,而在生产环境下,你可以通过压缩代码来减小体积优化性能。
-
devSever
开启一个本地服务器,实现热更新等服务
-
这里需要注意的是可以在webpack配置文件里添加代码/** @types {import('webpack').Configuration} */来实现webpack代码提示
//webpack配置文件
//给nodejs看的 遵循node模块规范
//src里面的遵循前端模块规范
//实现代码提示
/** @types {import('webpack').Configuration} */
const path = require("path");
//const devServer = require('webpack-dev-server');
module.exports = {
mode: "production",//设置打包的模式,production表示生产模式,development表示开发模式
entry: {
//对象的形式,属性home/load就为打包后生成的js的名字
home: './src/home.js',
load: './src/load.js'
},
output: {
filename: '[name].js',//打包后的文件名
path: __dirname + '/dist',//指定打包的目录,必须为绝对路径
},
//配置
module: {
rules: [
{
//在项目打包中并不是所有的文件都需要css-loader处理,所以在此处加上test筛选需要处 理的文件,正则表达式,匹配以.css结尾的文件。
test: /.css$/i,
//选择该文件用什么loader处理,一个loder只负责处理一项工作,loader执行顺序,从后往前 执行(先css后style)
use: ["style-loader", "css-loader"],
},
//url-loader只能处理样式表中引入的图片,
//而对于在html页面中通过引入的图片,url-loader是无法直接识别的,
//需要通过html-loader编译引入img,从而使得url-loader能够进一步处理它。
//因为url-loader默认使用es6模块化进行解析,
//而html-loader引入图片使用commonjs方式,解析时就会出问题,设置esModule: false解决。
{
test: /.(htm|html)$/i,
use: {
loader: 'html-loader',
options: {
esModule: false,
}
}
},
{
test: /.(png|jpg|gif)$/,
loader: "url-loader",
//为了告诉webpack将图片文件也视为JavaScript文件类型进行处理,以便于使用`url-loader`将图片转换为base64 URL。
type: 'javascript/auto',
// 设置配置选项
options: {
limit: 8 * 1024,
// 如果小于8kb使用base64 处理
// 优点 减少对服务器的请求,减轻服务器端压力
// 缺点 体积会变大
pulbicPath: "/",
outputPath: "./asset/",
name: "[name].[ext]", //ext保留原来的后缀名
esModule: false,//关闭es6模块化
}
},
],
},
plugins: [
new HTMLPlugin({
template: './src/home.html',
filename: 'home.html',
chunks: ['home'], //引入对应的js(对应(entry)中的入口文件)
}),
new HTMLPlugin({
template: './src/load.html',
filename: 'load.html',
chunks: ['load'],
}),
]
}
-
plugin
插件用来为webpack拓展功能,让webpack的功能更多样。(打包优化,资源管理,注入环境变量)。
htmlwebpackplugin
在进行项目部署的时候,是需要有对应的入口文件 index.html 的,所以我们需要添加html文件,htmlwebpackplugin插件可以在打包过后,自动在打包目录生成html页面
安装HtmlWebpackPlugin依赖:
npm i html-webpack-plugin -D
//在webpacK.config.js中配置
plugins: [
//构建函数创建一个对象,此时插件创建成功
new HTMLPlugin({
template: './src/home.html',
filename: 'home.html',
chunks: ['home'], //引入对应的js(对应(entry)中的入口文件)
}),
new HTMLPlugin({
template: './src/load.html',
filename: 'load.html',
chunks: ['load'],
}),
]
-
Babel
Babel 是一个 JavaScript 编译器。
在编写js代码时,使用的js的新特性在旧的浏览器中兼容性不好,从而导致我们无法使用这些新的特性。
Babel可以把使用ES6/ES7等“高级”语法编写的JavaScript代码转换为ES5/ES3的“通俗”语法(也可以把JSX语法转为JavaScript)其实,babel就是一个可以将es6的代码转换为es5的代码的插件,以提高代码的兼容性。
安装引入babel-loader
npm i -D @babel/core @babel/preset-env babel-loader
在webpack.config.js进行配置
/** 在rules下面进行配置 */
module: {
rules: [
{
test: /.m?js$/,
exclude: /(node_modules|bower_components)/,
//默认配置
use: {
loader: 'babel-loader',
options: {
presets: ['@babel/preset-env'],
},
},
},
];
}
先修改一下index.js里面的内容
document.body.onclick=()=>{
console.log("summer is ...");
}
运行npx webpack打包后可以看到main.js里的内容为:
document.body.onclick=()=>{console.log("summer is ...")};
在安装bable之后,再次打包之后可以看到main.js里的内容变为:
document.body.onclick= function () { console.log("summer is coming") };
热更新
开发模式和生产模式
- development 开发模式,即写代码的时候,在此模式下,为了提高开发效率,我们需要提高编译速度,配置热更新和跨域,以及快速debug。
- production 生产模式,即项目上线后,在此模式下,我们要打包一份可部署代码,需要对代码进行压缩,拆分公共代码以及第三方js库。
Mode 配置选项,可以告知 webpack 使用响应模式的内置优化:
- 默认值是 production
- 可选值有 'development' | 'production'
针对不同的mode,webpack会进行不同的优化配置,为了更好的定制化,我们需要自己来编写不同mode下的配置。
实现热更新
添加dev模式,得到一个开发服务器,同时实现热更新。
npm add -D webpack-dev-server
启动服务器:
npx webpack serve
之后会将代码部署到一个服务器上,当本地修改代码后会实现自动更新页面。
- 在scripts中配置dev后可以直接使用npm dev启动服务器。
//package.json
{
"name": "demo",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"build": "cross-env mode=PRODUCTION webpack",
//open表示自动打开浏览器网址,不需要再次点击。
"dev" : "webpack serve --open"
},
"keywords": [],
"author": "",
"license": "ISC",
"devDependencies": {
"cross-env": "^7.0.3",
"html-webpack-plugin": "^5.5.0",
"webpack": "^5.74.0",
"webpack-cli": "^4.10.0",
"webpack-dev-server": "^4.10.0"
}
}
修改src目录下的index.js
const element = document.createElement('div');
element.innerHTML = "hello world"
document.body.appendChild(element)
然后运行 npm dev,webpack会自动帮你开启一台本地服务器并打开浏览器,你将看到一个hello world。
vite
Vite是一个新的构建工具,它解决了webpack以下问题:
- 相比与webpack而言,它采用了不同的运行方式,webpack对项目采取先打包,再运行的措施,对于较大的项目运行速率会降低,vite并不在开发环境下对项目进行打包,直接用es模块的方式运行,只在项目部署时才对项目进行打包。
- 简单配置,快速开发,使用更加便利。
- 模块化方面,Vite基于浏览器原生ESM的支持实现模块加载,并且无论是开发环境还是生产环境,都可以将其他格式的产物(如Common-js)转换为ESM
- 语法转译方面,Vite内置了对Typescripts、JSX等高级语法的支持,也能够加载各种各样的静态资源,如图片、Worker等
- 产物质量方面,Vite基于成熟的打包工具Rollup实现生产环境打包,同时可以配合Terser、Babel等工具链。可以极大程度保证构建产物的质量。
快速创建项目,index.html不用再写在src下,用vite创建的项目默认的路径就是根目录。
// 三选一
npm create vite@latest
yarn create vite
pnpm create vite
启动vite项目:
npm init -y
npm add -D vite
npx vite