前端工程化

443 阅读9分钟

一.概览

1.流程图

graph TD
前端工程化 --> 原生JS升级+MVVM框架问题
前端工程化 --> vue2升级vue3+构建性能优化问题
前端工程化 --> 前端团队底层工程链路统一

2.前端开发模式演化

1733898292890.png

1733898515711.png

3.前端研发架构图

1657508777327.png

4.前端工程化解决什么问题?

1657509167405.png

5.企业前端工程化问题解法 (工程化核心三点:效率、规范、性能

  • 项目量级的增加:模块化(CommonJs和ESM)、npm、webpack
  • 项目数量的扩大:研发平台、研发脚手架(创建和发布)
  • 项目复杂度高:工程脚手架(统一解决不同技术栈的工程差异 vue、react、egg.js统一脚手架,用不同的loader来控制)
  • 团队人数增长:研发平台、研发脚手架

6.脚本和模块化的区别

1657510333151.png

7.前端模块化的进化过程

  1. 挂在全局的window下,多个js文件容易造成命名冲突

1657510529526.png

  1. 方法放在对象里面再挂载在window上 防止命名冲突(缺陷:里面的属性可以随便改无法私有,模块化核心私有性)。 1657510644292.png

1657526083735.png

1657527277833.png

  • 第五阶段 CommonJs 模块化规范

1657530681456.png

1.CommonJs 模块打包

1.安装browserify: npm i browserify -g
2.模块打包命令:browserify 入口js路径 -o 输出文件路径
eg: browserify module_test/cjs/entry.js -o dist/bundle.js
3.注意,当存在多个模块时,每个模块都需要单独打包

2.browserify打包原理

1.本质还是通过自执行函数实现模块化
2.将每个模块编号,存入一个对象,每个模块标记依赖模块
3.实现require方法,核心时通过call方法调用模块,并传入requiremoduleexports方法,
  通过module存储模块信息,通过exports存储模块输出信息

1657532143627.png

  1. AMD规范(require.js)
  2. CMD规范介绍 image.png 5.ESModule规范(ES6推出模块化 浏览器已支持ESModule,但所有模块都要引入,不能只引入入口文件)
    1.ES6模块化可以直接script引入浏览器使用但要把所有的依赖模块都引入
    2.webpack就是把这些依赖模块打包成一个文件引入,简化引入

1.Esmodule是希望在编译时确定模块的依赖关系
2.CommonJS和AMD必须在运行时才能确定依赖和输入、输出
3.ESM通过import加载模块 ,通过export输出模块

---
`6.CommonJs和ESModule规范对比`
1. CommonJs模块输出的是值的拷贝,es6模块输出的是值的引用
```js
//在es6模块中 值的引用
//1.在test.js
exports let a = 1;
exports function plus(){
    a++;
}
//2.在入口文件entry.js
import { a, plus } from './test.js'
console.log(a) //打印 1
plus();
console.lopg(a) //打印 2
//在CommonJs中 值得拷贝
//1.在test.js
let a = 1
exports.a = a
exports.plus = function(){
    a++
}
//2.在entry.js中
const { a, plus } require('./test.js')
console.log(a) //打印 1
plus();
console.lopg(a) //打印 1


//解释:在test.js中相当于
module.exports = {
    a:1,
    plus
}
//1.相当于let a = 1拷贝过来 加载的是模块里面的1 所以改变不了
//2.要想改变模块里面的1 则要写get和set方法
let a = 1
exports.a = a
exports.plus = function(){
    a++
}
exports.get = function(){
    return a
}
//2.在entry.js中 
const { a, plus,get } require('./test.js') 
console.log(a) //打印 1
plus();
console.lopg(a) //打印 1
console.lopg(get()) //打印 2
  1. CommonJs模块是运行时加载,ES6模块是编译时输出接口
  2. CommonJs时单个导出,ES Module可以导出多个
1.CommonJs只能导出一个对象
2.ESModule//(1)已经导出了
export let a=1;
export function plus(){
    a++;
}
//还可以再导出这样一个对象
export default {
    a:1,
    b:2
}

//(2)引入的时候
import value,{a,plus} from './test.js'
//想获取所有的模块
import * as mod from './test.js'
  1. CommonJs模块为同步加载,ES Module支持异步加载
//在 ES Module中支持 promise的方式加载
import ('./test.js').then(mod =>{
    console.log(mod)
    console.log(mod.default)
    mod.plus()
    console.log(mod.a)
})
  1. CommonJs的this是当前模块,ESimport6 Module的this是undifine
  2. CommonJs和ES Module的语法不同
1.CommonJs使用 module.exportsrequire
2.ES Module使用 exportimport

1657536913705.png 1657536990589.png


7.npm

  • 诞生背景 1657609517923.png
  • npm介绍
    (1)npm解决的核心问题是模块化管理问题
    (2)npm包含cli、模块仓库、官网三大部分
    (3)npm介绍
  • npm原理分析
    解释:
    (1)npm publish 上传到 registry仓库
    (2)private是私有仓库(靠这个收费)
    (3)publish为公有仓库,其中normal是普通仓库而 organization为组织仓库前面加@符号
    1657609806308.png 原理总结:

1.npm init创建模块 npm install安装模块,npm publish发布模块
2.npm link 本地开发 npm config调整配置,npm run调用scripts
3.npm规范:package.json管理模块信息,node_modules保存依赖

  • npm缺陷
    (1)npm只能解决模块的高效管理和获取问题
    (2)npm无法解决加载性能问题
    (3)模块化发明后,制约其广泛应用的因素就是性能问题

8.webpack

  • 原理
    (1)最初webpack核心解决的问题就是代码的合并和拆分
    (2)webpack的核心理念是将资源都视为模块,统一进行打包和处理
    (3)webpack提供了loader和plugins完成功能扩展
    1657610744714.png webpack核心原理就是先合并再分割 1657611013673.png

  • webpack核心概念
    (1) webpack优化主要针对 chunk中间文件 进行优化 1657611439527.png
    (2) 开始一个简单的项目 1657611852431.png

//yarn add webpack webpack-cli -D 安装webpack和webpack-cli
const path = require("path");
module.exports = {
  entry: "./src/index.js",
  output: {
    path: path.join(__dirname, "./dist"),
    filename: "bundle.js",
  },
  mode: "development",//开发模式
  devtool: "source-map",//代码的映射
  module: {
    rules: [
      {
        test: /.css$/,
        //1.css-loader将css模块化
        //2.style-loader将css插入到header中
        use: ["style-loader", "css-loader"],
      },
    ],
  },
};

(3)自定义loader
意义:loader是来解决文件类型转换的问题

//1.建一个test.imooc文件
<script>
 export default {
     a:1,
     b:2
 }
</script>

//2.webpack.config.js中配置自定义loader
module: {
    rules: [
      {
        test: /\.imooc$/,
        use: [path.join(__dirname, "./loader/imooc-loader.js")],
      },
    ],
},

//3.建一个 imooc-loader.js
const REG = /<script>([\s\S]+?)<\/script>/;
module.exports = function (source) {
  const __source = source.match(REG);
  return __source && __source[1] ? __source[1] : source;
};

//判断当前模块是否为主模块  对loader单独测试用  (node imooc-loader.js运行会执行)
if (require.main === module) {
  const source = `<script>
        export default {
            a:1,
            b:2
        }
    </script>`;
  const match = source.match(REG);
  console.log(match);
}

(4)plugin
意义:plugin解决文件的变更、压缩、定制等

1657620986785.png webpack hooks
compiler钩子
compilation 钩子

  • 自定义plugin
//1.新建文件 FooterPlugin.js
const { ConcatSource } = require("webpack-sources"); //做webpack源码的更新
class FooterPlugin {
  constructor(options) {
    this.options = options;
  }
  apply(compiler) {
      //编译(compilation)创建之后,注册组件
    compiler.hooks.compilation.tap("FooterPlugin", (compilation) => {
    //优化完 对Assets资源进行处理 钩子
      compilation.hooks.processAssets.tap("FooterPlugin", () => {
      console.log(compilation.chunks, "打印的如下图所示");
        for (const chunks of compilation.chunks) {
          for (const file of chunks.files) {
            //拿到文件 如 bundle.js
            console.log(file, "file");
            //this.options.banner 拿到我们传入的banner
            const comment = `/* ${this.options.banner} */`;
            compilation.updateAsset(
              file,
              (old) => new ConcatSource(old, "\n", comment)//把注释更新到bundle.js下面
            );
          }
        }
      });
    });
  }
}
module.exports = FooterPlugin;

//2.在webpack.config.js中
const FooterPlugin = require("./plugin/FooterPlugin.js");
plugins: [
    new webpack.BannerPlugin({
      banner: "欢迎进入科幻世界",
    }),
    new FooterPlugin({//new一个FooterPlugin对象 传入banner
      banner: "好的,我来了等我",
    }),
  ],

compilation.chunks打印的内容 1657683846676.png

9.ZBasetpc项目改造

总览图: webpack改造2.png (1)源码存在的问题 1657702082447.png (2)项目预备知识梳理

1657702527952.png (3)webpack.config.js文件内容

const path = require("path");
const HtmlWebpackPlugin = require("html-webpack-plugin"); //生成一个html文件 并把打包的js引入
const { CleanWebpackPlugin } = require("clean-webpack-plugin");
const webpack = require("webpack");
const { ProvidePlugin } = require("webpack");
module.exports = {
  entry: {
    bundle: "./src/index.js",
  },
  output: {
    path: path.join(__dirname, "./dist"),
    filename: "js/[name].js", //[hash].js 生成不同打包js文件名
  },
  mode: "development",
  module: {
    rules: [
      {
        test: /\.css$/,
        use: ["style-loader", "css-loader"],
      },
      //webpack5可以用下面替换url-loader
      {
        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]",
        },
      },
    ],
  },
  plugins: [
    //多个页面要new 多个HtmlWebpackPlugin
    new HtmlWebpackPlugin({
      filename: "index.html", //模板名称
      template: "./src/index.html", //模板路径
    }),
    new HtmlWebpackPlugin({
      filename: "login.html", //模板名称
      template: "./src/login.html", //模板路径
    }),
    new CleanWebpackPlugin(),
    new webpack.ProvidePlugin({
      //对jquery做映射
      $: "jquery",
      jQuery: "jquery",
    }),
  ],
};

(4) 性能优化

  • js分离
    意义:防止全部页面都引用bundle.js比较臃肿
1.不同页面建不同的js  分别引入各自页面需要的js和css  如:login.js和index.js
2.在webpack.config.js中配置多入口
module.exports = {
    //配置多个入口文件 会分index打包和login打包
    entry: {
        index: "./src/index.js",
        login: "./src/login.js",
    },
    //多打包js和模板作映射
    plugins: [
        //多个页面要new 多个HtmlWebpackPlugin
        new HtmlWebpackPlugin({
          filename: "index.html", //模板名称
          template: "./src/index.html", //模板路径
          chunks: ["index"], //这里配置index会把entry里面的index入口文件打包到index.html中
        }),
        new HtmlWebpackPlugin({
          filename: "login.html", //模板名称
          template: "./src/login.html", //模板路径login
          chunks: ["login"], //这里配置login会把entry里面的login入口文件打包到index.html中
        })
  ],
}

(5) 让当前项目具备开发模式
意义:不用打包后才能看到效果,一修改就看到效果

1.安装webpack-dev-server  yarn add webpack-dev-server -D
2.在webapck.config.js中配置 devServer
module.exports = {
  devServer: {
    static: {
      //给出静态资源文件的路径
      directory: path.join(__dirname, "dist"),
    },
    compress: true, //启动压缩
    port: 9000, //端口号
    hot: true, //热启动
  },
}
3.在package.json中 添加start启动
"scripts": {
    "start":"webpack-dev-server"
  },

(6)拷贝图片到dist目录
意义:用服务跑起来后图片丢失
注意:copy-webpack-plugin 会拷贝到硬盘里所以看不见 可以通过npm run build看见

1)安装 yarn add copy-webpack-plugin -D
    (2)在webpack.config.jsconst CopyWebpackPlugin = require("copy-webpack-plugin");
    module.exports = {
        plugins: [
            new CopyWebpackPlugin({
              //patterns用来匹配路径
              patterns: [
                {
                  //从./src/img拷贝到./dist/img
                  from: path.resolve(__dirname, "./src/img"),
                  to: path.resolve(__dirname, "./dist/img"),
                },
              ],
            }),
        ]
    }
   (3) 显示不出 注意修改图片路径

(7) css分离优化 将css独立出来

//1.安装 yarn add mini-css-extract-plugin -D  对css解压剥离
//2.在webpack.config.js中对css剥离再生成css文件
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
module.exports = {
    module: {
        rules: [
          //style-loader通过添加dom方式引入css
          {
            test: /\.css$/,
            //使用 MiniCssExtractPlugin.loader 对css进行剥离
            use: [MiniCssExtractPlugin.loader, "css-loader"],
          },
      ]
   },
   plugins: [
       new MiniCssExtractPlugin({
          filename: "css/[name].css", //剥离完在css目录下生成[name].css的文件
          chunkFilename: "css/[name].chunk.css", //生成chunk文件的名称
       }),
   ]
}

1657788476218.png (8)对css和js继续压缩
介绍:主要就是去掉文件中的空格、注释、缩进

//1.安装npm i -D uglifyjs-webpack-plugin 对js压缩
//2.安装 yarn add css-minimizer-webpack-plugin -D 对css进行压缩
//2.在webpack.config.js中
const UglifyJsPlugin = require("uglifyjs-webpack-plugin");
const CssMinimizerPlugin = require("css-minimizer-webpack-plugin");
module.exports = {
  //在模块化 loader之后处理优化的
  optimization: {
    //开启后 在development模式下也可以对代码压缩   默认在mode: "development"代码不压缩
    minimize: true, 
    minimizer: [
      new UglifyJsPlugin({
        sourceMap: true, //压缩后也可以使用sourceMap的功能
      }),//压缩js
      new CssMinimizerPlugin(),//压缩css
    ],
  },
}

(9)打包把无用的代码删除掉
lodash为例 触发treeshaking的条件

//! 1.在esModule中通过解构的获取的方式,可以触发 treeshaking
//! 2.调用的npm包必须使用EsModule模块 export defalut xx
补充:
//! 3.同一文件的treeshaking有触发条件,条件就是mode=production
//! 4.一定要注意使用解构来加载模块。  export导出 import { get } from "lodash-es";引入

//直接使用loadsh 因为 loadsh是module.export导出的 所以无法触发treeshaking
import { get } from "lodash";
//lodash-es是通过export default 导出的可以触发treeshaking
import { get } from "lodash-es";
console.log(get({ a: 1 }), "a");

(10)代码分割通过splitChunks(把第三方包和业务代码做分割)

module.exports = {
    //在模块化 loader之后处理优化的
  optimization: {
    minimize: true, //开启后 在development模式下也可以对代码压缩   默认在mode: "development"代码不压缩
    minimizer: [
      new UglifyJsPlugin({
        sourceMap: true, //压缩后也可以使用sourceMap的功能
      }),
      new CssMinimizerPlugin(),
    ],
    splitChunks: {
      //将node_module和我们源码作分割
      minSize: 30 * 1024, //表示包大于30kb的才做分割  打包的包最好不要大于300kb
      chunks: "all",
      name: "common", //对chunks包重命名
      cacheGroups: {
        //cacheGroups对特定的库单独打包
        jquery: {
          //对jquery单独打包
          name: "jquery",
          test: /jquery\.js/,
          chunks: "all",
        },
        "lodash-es": {
          //对lodash-es单独打包
          name: "lodash-es",
          test: /lodash-es/,
          chunks: "all",
        },
      },
    },
  },
}

1657870689592.png (11)通过ejs模板 将公共代码抽离

//1.安装 yarn add ejs-loader -D
//2.在规则 rules里面添加
{
    test: /\.ejs/,
    loader: "ejs-loader",
    options: {
      esModule: false,
    },
},
//3.建一个header.ejs文件  将公共代码放入文件
//4.把公共的代码文件放入 需要的文件中
<!----把 head 独立出来引入 title可以传参------->
<%=require('./ejs/header.ejs')({title:'首页'}) %>

1657872277402.png

性能优化后完整配置

const path = require("path");
const HtmlWebpackPlugin = require("html-webpack-plugin"); //生成一个html文件 并把打包的js引入
const { CleanWebpackPlugin } = require("clean-webpack-plugin");
const webpack = require("webpack");
const { ProvidePlugin } = require("webpack");
const CopyWebpackPlugin = require("copy-webpack-plugin");
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
const UglifyJsPlugin = require("uglifyjs-webpack-plugin");
const CssMinimizerPlugin = require("css-minimizer-webpack-plugin");
module.exports = {
  entry: {
    index: "./src/index.js",
    login: "./src/login.js",
  },
  output: {
    path: path.join(__dirname, "./dist"),
    filename: "js/[name].js", //[hash].js 生成不同打包js文件名
  },
  devServer: {
    static: {
      //给出静态资源文件的路径
      directory: path.join(__dirname, "dist"),
    },
    compress: true, //启动压缩
    port: 9000, //端口号
    hot: true, //热启动
  },
  mode: "development",
  module: {
    rules: [
      //style-loader通过添加dom方式引入css
      {
        test: /\.css$/,
        //使用 MiniCssExtractPlugin.loader 对css进行剥离
        use: [MiniCssExtractPlugin.loader, "css-loader"],
      },
      //webpack5可以用下面替换url-loader
      {
        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]",
        },
      },
      {
        test: /\.ejs/,
        loader: "ejs-loader",
        options: {
          esModule: false,
        },
      },
    ],
  },
  //在模块化 loader之后处理优化的
  optimization: {
    minimize: true, //开启后 在development模式下也可以对代码压缩   默认在mode: "development"代码不压缩
    minimizer: [
      new UglifyJsPlugin({
        sourceMap: true, //压缩后也可以使用sourceMap的功能
      }),
      new CssMinimizerPlugin(),
    ],
    splitChunks: {
      //将node_module和我们源码作分割
      minSize: 30 * 1024, //表示包大于30kb的才做分割  打包的包最好不要大于300kb
      chunks: "all",
      name: "common", //对chunks包重命名
      cacheGroups: {
        //cacheGroups对特定的库单独打包
        jquery: {
          //对jquery单独打包
          name: "jquery",
          test: /jquery\.js/,
          chunks: "all",
        },
        "lodash-es": {
          //对lodash-es单独打包
          name: "lodash-es",
          test: /lodash-es/,
          chunks: "all",
        },
      },
    },
  },
  plugins: [
    //多个页面要new 多个HtmlWebpackPlugin
    new HtmlWebpackPlugin({
      filename: "index.html", //模板名称
      template: "./src/index.html", //模板路径
      chunks: ["index"], //这里配置index会把entry里面的index入口文件打包到index.html中
    }),
    new HtmlWebpackPlugin({
      filename: "login.html", //模板名称
      template: "./src/login.html", //模板路径login
      chunks: ["login"], //这里配置login会把entry里面的login入口文件打包到index.html中
    }),
    new CleanWebpackPlugin(),
    new webpack.ProvidePlugin({
      //对jquery做映射
      $: "jquery",
      jQuery: "jquery",
    }),
    new CopyWebpackPlugin({
      //patterns用来匹配路径
      patterns: [
        {
          //从./src/img拷贝到./dist/img
          from: path.resolve(__dirname, "./src/img"),
          to: path.resolve(__dirname, "./dist/img"),
        },
      ],
    }),
    new MiniCssExtractPlugin({
      filename: "css/[name].css", //剥离完在css目录下生成[name].css的文件
      chunkFilename: "css/[name].chunk.css", //生成chunk文件的名称
    }),
  ],
};


10.自己搭建基本vue2项目

1.yarn init -y
2.yarn add webpack webpack-cli -D
3.yarn add vue@2.6.14(与vue-template-compile版本号保持一致)
4.yarn add @vue/compiler-sfc vue-template-compiler@2.6.14 vue-loader@15.9.8 -D
5.yarn add html-webpack-plugin clean-webpack-plugin webpack-dev-server -D

1658128856413.png

11.vue的SPA(单)应用改造

//@vue/compiler-sfc解析模板,style,script
//用vue-cli搭建vue 下面这些都会被安装好
1.安装 yarn add @vue/compiler-sfc vue-template-compiler vue-loader@15.9.8 -D 

问题 1658116213555.png 解决:要使用vue配套的plugin

const VueLoaderPlugin = require("vue-loader/lib/plugin")
plugins:[
    new VueLoaderPlugin()
]

vue单页面配置

//webpack.config.dev.js
const path = require("path");
const HtmlWebpackPlugin = require("html-webpack-plugin"); //生成一个html文件 并把打包的js引入
const { CleanWebpackPlugin } = require("clean-webpack-plugin");
const webpack = require("webpack");
const { ProvidePlugin } = require("webpack");
const CopyWebpackPlugin = require("copy-webpack-plugin");
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
const UglifyJsPlugin = require("uglifyjs-webpack-plugin");
const CssMinimizerPlugin = require("css-minimizer-webpack-plugin");

const VueLoaderPlugin = require("vue-loader/lib/plugin");//新加
module.exports = {
  entry: {
    index: path.resolve(__dirname, "../src/main.js"),//修改
  },
  output: {
    path: path.join(__dirname, "../dist"),
    filename: "js/[name].js", //[hash].js 生成不同打包js文件名
  },
  devServer: {
    static: {
      //给出静态资源文件的路径
      directory: path.join(__dirname, "dist"),
    },
    compress: true, //启动压缩
    port: 9000, //端口号
    hot: true, //热启动
  },
  mode: "development",
  module: {
    rules: [
      //style-loader通过添加dom方式引入css
      {
        test: /\.css$/,
        //使用 MiniCssExtractPlugin.loader 对css进行剥离
        use: [MiniCssExtractPlugin.loader, "css-loader"],
      },
      //webpack5可以用下面替换url-loader
      {
        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]",
        },
      },
      {
        test: /\.ejs/,
        loader: "ejs-loader",
        options: {
          esModule: false,
        },
      },
      //新加
      {
        test: /\.vue$/,
        loader: "vue-loader",
      },
    ],
  },
  //在模块化 loader之后处理优化的
  optimization: {
    minimize: true, //开启后 在development模式下也可以对代码压缩   默认在mode: "development"代码不压缩
    minimizer: [new UglifyJsPlugin(), new CssMinimizerPlugin()],
    splitChunks: {
      //将node_module和我们源码作分割
      minSize: 30 * 1024, //表示包大于30kb的才做分割  打包的包最好不要大于300kb
      chunks: "all",
      name: "common", //对chunks包重命名
      cacheGroups: {
        //cacheGroups对特定的库单独打包
        jquery: {
          //对jquery单独打包
          name: "jquery",
          test: /jquery\.js/,
          chunks: "all",
        },
        "lodash-es": {
          //对lodash-es单独打包
          name: "lodash-es",
          test: /lodash-es/,
          chunks: "all",
        },
      },
    },
  },
  plugins: [
    //新加 修改
    new HtmlWebpackPlugin({
      filename: "index.html", //模板名称
      template: path.resolve(__dirname, "../public/index.html"), //模板路径
      chunks: ["index"], //这里配置index会把entry里面的index入口文件打包到index.html中
    }),
    new CleanWebpackPlugin(),
    new webpack.ProvidePlugin({
      //对jquery做映射
      $: "jquery",
      jQuery: "jquery",
    }),
    new CopyWebpackPlugin({
      //patterns用来匹配路径
      patterns: [
        {
          //从./src/img拷贝到./dist/img
          from: path.resolve(__dirname, "../src/img"),
          to: path.resolve(__dirname, "../dist/img"),
        },
      ],
    }),
    new MiniCssExtractPlugin({
      filename: "css/[name].css", //剥离完在css目录下生成[name].css的文件
      chunkFilename: "css/[name].chunk.css", //生成chunk文件的名称
    }),
    new VueLoaderPlugin(),
  ],
};

12 vue的mpa(多)页面应用

在vue单页面配置基础上配置多页面应用 1658201305809.png

13.vue2.0升级vue3.0

注意:vue-loader 在16版本以上才匹配vue3

  1. 升级库
//下面这些库做升级
"vue-loader": "^17.0.0",
"vue": "^3.2.37",
"vue-router": "^4.1.2"
  1. 修改vue-loader引入问题: 1658212735104.png
    解决:
//在webpack.config.js中
//vue2 引法
const VueLoaderPlugin = require("vue-loader/lib/plugin");
//vue3 引法
const { VueLoaderPlugin } = require("vue-loader");

3.修改语法问题

  • main.js中
//import Vue from "vue"; //vue2
import { createApp } from "vue"; //vue3
import App from "./App.vue";
import router from "./router";

//!vue2写法
// new Vue({
//   router,
//   render: (h) => h(App),
// }).$mount("#app");

//!vue3写法
createApp(App).use(router).mount("#app");
  • 路由router.js中
//vue2 写法
import Vue from "vue";
import Router from "vue-router";
import Home from "../Home.vue";
import Login from "../Login.vue";
Vue.use(Router);
export default new Router({
  routes: [{
      path: "/",
      redirect: "/home",
    },{
      path: "/home",
      name: "Home",
      component: Home,
    },{
      path: "/login",
      name: "Login",
      component: Login,
    },
  ],
});


//vue3写法
import { createRouter, createWebHashHistory } from "vue-router";
import Home from "../Home.vue";
import Login from "../Login.vue";

const router = createRouter({
  history: createWebHashHistory(),
  routes: [
    {
      path: "/",
      redirect: "/home",
    },
    {
      path: "/home",
      name: "Home",
      component: Home,
    },
    {
      path: "/login",
      name: "Login",
      component: Login,
    },
  ],
});
export default router;