前端工程化续1

448 阅读5分钟

一.项目2 vue2-elm项目工程化升级

这个项目是5年前 vue-cli2创建项目 带build目录 比较老

升级流程图

vue项目升级.png

1.准备工作

  • vue-cli2构建源码分析 1658218974237.png
//1.cross-env NODE_ENV=online表示 通过cross-env这个库设置环境变量NODE_ENV等于online
//2.获取环境变量可以通过  process.env.NODE_ENV
"scripts": {
    "dev": "cross-env NODE_ENV=online node build/dev-server.js",
    "local": "cross-env NODE_ENV=local node build/dev-server.js",
    "build": "node build/build.js"
  },
  
  //1.http-proxy-middleware express中启动代理服务的中间件 解决跨域问题
  //2.webpack-dev-middleware //webpack-dev-server底层实现的中间件
  • vue-cli开发模式下 都会采用express启动静态资源服务器 1658220869397.png

2.webpack-dev-middleware 详解

1659600535383.png

3.webpack-hot-middleware 详解

1659602119437.png

4.express创建

//1.创建服务
const express = require("express")
const app = express()

//中间件  处理请求业务逻辑
//前置中间件
//---------中间件第一个参数为回调函数时,则针对所有请求都有效
app.use(function(req,res,next){
    console.log('middleware')
    next()
});

//----------路由中间件,第一个参数为匹配路由,第二个参数为回调函数
app.use('/test',function(req,res,next){
    res.send('test')
    throw new Error('error message')
    next()
})
//获取静态资源
app.use('/static',express.static('./static'))

//------异常中间件  回调函数包含了4个参数
//! 1.异常中间件全局只包含一个 (多个时只会执行第一个)
//! 2.异常中间件可以传递给普通中间件
//! 3.异常中间件需要放在所有中间件的最后 (可以捕获所有异常)
//! 4.异常中间件只能捕获回调函数中的异常,无法捕获promise的异常  此时需要全局的promise异常捕获<unhandledRejection>
app.use(function(err,req,res,next){
    console.error('err!',err.message)
})
//2.拦截路由
app.get('/',function(req,res,next){
    console.log('handle /')
    res.send('<html><body><div style="color:red">111</div></body></html>')
    next()
});

//---------后置中间件
app.use(function(req,res,next){
    console.log('after niddlewere')
})

//3.启动服务
const port = 9090
app.listen(port,function(){
    console.log('服务启动成功端口号为:'+port)
})

//! 全局的异常捕获
process.on('uncaughtException',function(err){
    console.error('uncaughtException',err.message)
})
//! 全局的promise异常捕获
process.on('unhandledRejection',function(err){
    console.error('unhandledRejection',err.message)
})

二.vue的升级改造

graph TD
vue2-elm-master项目工程化升级 --> 第一阶段:vue升级改造升级vue3
vue2-elm-master项目工程化升级 --> 第二阶段:webpack打包改造
vue2-elm-master项目工程化升级 --> 第三阶段:项目打包构建优化

介绍:为什么要升级到vue3

image.png

  • vue2对ts支持不太友好
  • vue2过度依赖this,导致无法进行treeshaking

vue3的优势
1659604068546.png

第一阶段:项目升级vue3

(1)github上下载vue2-elm-master项目,并初始化

(2)vue全家桶依赖升级

//原来版本
"vue": "^2.1.0",
"vue-router": "^2.1.1",
"vuex": "^2.0.0"

//升级后版本
"vue": "^3.0.0",
"vue-router": "^4.0.0-0",
"vuex": "^4.0.0-0"
//1.删除掉原来devDependencies里面所有的依赖
//2.配置vue3需要的依赖
"devDependencies": {
    "@vue/cli-service":"5.0.0-beta.2",
    "@vue/compiler-sfc":"3.2.6"
    "sass":"1.49.7",
    "sass-loader":"12.4.0",
    "webpack":"5.50.0",
    "webpack-cli":"4.9.2"
},
//3.在package.json中 修改
"scripts": {
    "dev": "vue-cli-service serve",
    "build": "vue-cli-service build"
  },

遇到的编译上的问题: 1659666458001.png

1659666931022.png

1659667414549.png

(3)vuex和vue-router语法升级

1659669013844.png

//代码
//在store/index.js中
import { createStore } from "vuex";
export default createStore({})
//使用方式
import {useStore} from 'vuex'
let store = useStore();
store.state.latitude
store.commit('xx'.data)

//在入口main.js中
import { createApp } from "vue";
import App from "./App.vue";
import store from "./store/";

createApp(App).use(store).mount("#app");

1659669445675.png

(4) 接口升级(地址替换成线上)

1659671530488.png

(5)图片地址的修改 换成线上

1659671444674.png

(6)样式的调整

1659680805450.png

(7)移植首页

第三阶段:项目打包构建优化

1.构建性能优化方法

1659684427787.png

(1)构建速度分析 speed-measure-webpack-plugin

speed-measure-webpack-plugin

//1.安装 npm i -D speed-measure-webpack-plugin
//2.在vue.config.js中
const path = require("path");
const SpeedMeasureWebpackPlugin = require("speed-measure-webpack-plugin");
//看下环境变量是否被写入
console.log("process.env.MEASURE", process.env.MEASURE);
const smp = new SpeedMeasureWebpackPlugin({
  /*
    3.使用环境变量的方式 控制是否要开启构建速度分析
    (1)安装 npm i cross-env -D 
    (2)在package.json中
    "scripts": {
      "serve": "cross-env MEASURE=true vue-cli-service serve",//MEASURE=true的时候就开启
      "build": "vue-cli-service build"
    },
  */
  disable: !(process.env.MEASURE === "true"), //是否开启构建速度分析 默认false开启的  注意是string格式所以要这样写
  outputFormat: "humanVerbose", //输出的日志格式
});
//!使用 smp.wrap()包裹配置
module.exports = {
  configureWebpack: smp.wrap({
    resolve: {
      alias: {
        src: path.resolve(__dirname, "./src"),
        assets: path.resolve(__dirname, "./src/assets"),
        components: path.resolve(__dirname, "./src/components"),
      },
    },
  }),
};

1659685577798.png

(2)构建体积分析

webpack-bundle-analyzer 会自动弹出一个页面介绍打包详情

//1.安装 npm i webpack-bundle-analyzer -D
//2.在配置文件中
const BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin;
module.exports = {
  plugins: [
    new BundleAnalyzerPlugin({
        //关闭弹出构建体积分析 disabled
        //使用环境变量的方式来判断是否开启体积分析
        analyzerMode: process.env.MEASURE === "true" ? "server" : "disabled", 
    })
  ]
}

1659690335407.png

2.构建速度的优化

(1)使用thread-laoder多进程构建

parallel vue中是否开启多进程

module.exports = {
   //parallel此属性为vue内部封装的thread-loader 为true表示开启多进程  
   //只能用于生产模式即 npm run build
  parallel: true,
  configureWebpack: smp.wrap({
    
  }),
};

//require("os").cpus()  查看当前电脑cpu

(2)使用dll做分包

注意要使用copy-webpack-plugin将生成的dll文件拷贝到dist目录下

//建webpack.dll.conf.js
const path = require("path");
const webpack = require("webpack");
const dllPath = "../dll";
module.exports = {
  mode: "production",
  entry: {
    vue: ["vue", "vue-router", "vuex"],
  },
  output: {
    path: path.resolve(__dirname, dllPath),
    filename: "[name].dll.js",
    library: "[name]_[hash]",
  },
  plugins: [
    new webpack.DllPlugin({
      path: path.join(__dirname, dllPath, "[name]-manifest.json"),
      name: "[name]_[hash]",
      context: process.cwd(), //为当前根目录
    }),
  ],
};

(3)使用cache缓存

1659694766088.png

(4)图片的压缩 image-webpack-loader

1659695324396.png

(5)删除css未使用的内容 purgecss-webpack-plugin

purgecss-webpack-plugin

1659695864461.png

第二阶段 加餐webpack4和webpack5比较

1.webpack5 treeshaking的能力更强

引入但没有使用的模块 webpack5会被忽略掉
同样是打包console.log 结果对比如下 1659756168239.png

2.cache缓存上的区别

//配置不同
//webpack4中
只能设置 cache:true

//webpack5中 可以设置
cache:{
    type:'filesystem'
    cacheDirectory:path.resolve(__dirname,'./node_modules/.cache_temp')
}

1659756789592.png

3.hard-source-webpack-plugin 缓存

支持3版本及以下版本进行缓存,并且可以让4版本进行向webpack5一样配置缓存目录

const HardSourceWebpackPlugin = require('hard-source-webpack-plugin')

plugins:[
    new HardSourceWebpackPlugin({
        cacheDirectory:path.resolve(__dirname,'./node_modules/.cache_temp')
    })
]

4.文件图片打包的不同

//webpack4
必须要使用url-loader 和 file-loader

//webpack5中可以使用 asset 不用安装loader
module:{
    rules:[
      {
        test: /\.(png|svg|jpg|jpeg|gif)$/i,
        type: "asset", //启动webpack5内置的moduleAsset属性(webpack5版本以上支持)
        parser: {
          dataUrlCondition: {
            maxSize: 8 * 1024, //表示小于8kb的图片转成base64打包到bundle.js中 否则直接输出到目录
          },
        },
        generator: {
          //在images目录中保存 name名称 hash名称(防止重名)  ext后缀名  [hash:6]表示hash值保存6位
          filename: "images/[name].[hash:6][ext]",
        },
      }
    ]
}

5.URIs不同

1659927182689.png 注意:打包https时需要配置以下 1659927305908.png

6. Treeshaking和sideEffects(副作用)

  1. webpack4无法对export default 进行Treeshaking而webpack5可以
  2. webpack5使用了sideEffects可以精确的控制哪些文件没有副作用,从而不打包 1659928130237.png

7.模块联邦(微前端的实现方式)

//引入
const ModuleFederationPlugin = require('webpack/lib/container/ModuleFederationPlugin')
  • 子应用1659929489303.png
  • 主应用1659929584364.png 1659929670571.png

8.packageExports

在webpack5+支持 一个lib包可以同时支持node和浏览器

//在package.json中配置
"exports":{
    //require引入lib包时拿到a.js的东西 
    //可以使用node的内置api fs/path/os/child——process
    "require":"./a.js",
    //import引入lib包时拿到b.js的东西
    //可以使用浏览器内置api document/window/dom/bom
    "import":"./b.js",
}