【2023秋第10节课】前端工程化

249 阅读7分钟

QQ图片20231028231625.png

本文编写自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-loader

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