一.概览
1.流程图
graph TD
前端工程化 --> 原生JS升级+MVVM框架问题
前端工程化 --> vue2升级vue3+构建性能优化问题
前端工程化 --> 前端团队底层工程链路统一
2.前端开发模式演化
3.前端研发架构图

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

5.企业前端工程化问题解法 (工程化核心三点:效率、规范、性能)
- 项目量级的增加:模块化(CommonJs和ESM)、npm、webpack
- 项目数量的扩大:研发平台、
研发脚手架(创建和发布) - 项目复杂度高:工程脚手架(统一解决不同技术栈的工程差异
vue、react、egg.js统一脚手架,用不同的loader来控制) - 团队人数增长:研发平台、研发脚手架
6.脚本和模块化的区别

7.前端模块化的进化过程
- 挂在全局的window下,多个js文件容易造成命名冲突
- 方法放在对象里面再挂载在window上 防止命名冲突(缺陷:里面的属性可以随便改无法私有,模块化核心私有性)。


-
第五阶段 CommonJs 模块化规范

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方法调用模块,并传入require、module、exports方法,
通过module存储模块信息,通过exports存储模块输出信息

- AMD规范(require.js)
- CMD规范介绍
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
- CommonJs模块是运行时加载,ES6模块是编译时输出接口
- 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'
- CommonJs模块为同步加载,ES Module支持异步加载
//在 ES Module中支持 promise的方式加载
import ('./test.js').then(mod =>{
console.log(mod)
console.log(mod.default)
mod.plus()
console.log(mod.a)
})
- CommonJs的this是当前模块,ESimport6 Module的this是undifine
- CommonJs和ES Module的语法不同
1.CommonJs使用 module.exports 和 require
2.ES Module使用 export 和 import

7.npm
诞生背景
npm介绍
(1)npm解决的核心问题是模块化管理问题
(2)npm包含cli、模块仓库、官网三大部分
(3)npm介绍npm原理分析
解释:
(1)npm publish 上传到 registry仓库
(2)private是私有仓库(靠这个收费)
(3)publish为公有仓库,其中normal是普通仓库而 organization为组织仓库前面加@符号
原理总结:
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完成功能扩展
webpack核心原理就是先合并再分割

-
webpack核心概念
(1) webpack优化主要针对 chunk中间文件 进行优化
(2) 开始一个简单的项目
//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解决文件的变更、压缩、定制等
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打印的内容

9.ZBasetpc项目改造
总览图:
(1)源码存在的问题
(2)项目预备知识梳理
(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.js中
const 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文件的名称
}),
]
}
(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",
},
},
},
},
}
(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:'首页'}) %>

性能优化后完整配置
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
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
问题
解决:要使用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单页面配置基础上配置多页面应用

13.vue2.0升级vue3.0
注意:vue-loader 在16版本以上才匹配vue3
- 升级库
//下面这些库做升级
"vue-loader": "^17.0.0",
"vue": "^3.2.37",
"vue-router": "^4.1.2"
- 修改vue-loader引入问题:

解决:
//在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;


