无规矩不成方圆,特别是vue3时代的setup编写方式,如果团队人员都随意发挥,维护是一场灾难。
所以在此定义了团队界面模版:
/**
* @name: index
* @author: weiyong
* @date: 2022-10-07 12:03
* @description:index
* @update: 2022-10-07 12:03
*/
<template>
<div :class="prefixCls">
界面内容
</div>
</template>
<script lang="ts">
import {defineComponent} from 'vue';
export default defineComponent({
components: {},
name: "index",
});
</script>
<script lang="ts" setup>
import {useDesign} from "@/hooks/web/useDesign";
const {prefixCls} = useDesign('index');
</script>
<style type="text/css" lang="less">
@prefix-cls: ~'@{namespace}-index';
.@{prefix-cls} {
background-color: #FFF;
}
</style>
- 第一:开始部分需要说明创建人,创建时间等相关信息
- 第二:界面的开头通过prefixCls 来定义顶层样式,为了解决样式重复、冲突等副作用
- 第三:prefixCls通过一个前缀+拼接的方式来生成,通过一个hooks来实现。方便今后统一修改前缀。
- 第四:统一采用setup的编写方式。
- 第五:通过defineComponent方式来申明组件的name,一般组件不需要defineComponent来说明名称,但如果动态组件注入需要说明name,就必须使用。
- 第六:采用less处理样式,不建议使用scss
useDesign的实现非常简单:
export function useDesign(scope: string) {
const values = {prefixCls:'xm'}
return {
prefixCls: `${values.prefixCls}-${scope}`,
prefixVar: values.prefixCls,
};
}
注意:如果第一次配置,可能会报@{namespace}没有定义的错误,这个需要配置vue.config.js的less参数
const oneOfsMap = config.module.rule("less").oneOfs.store;
oneOfsMap.forEach(item => {
item
.use("style-resources-loader")
.loader("style-resources-loader")
.options({
// or an array : ["./path/to/vars.less", "./path/to/mixins.less"] 这里的路径不能使用@,否则会报错
patterns: "./src/style/subApp.less"
})
.end()
});
完整的config.js可以参考
const { defineConfig } = require("@vue/cli-service");
const CompressionWebpackPlugin = require("compression-webpack-plugin");
const productionGzipExtensions = /\.(js|css|json|txt|html|ico|svg)(\?.*)?$/i; // 开启gzip压缩, 按需写入
const name = require("./package").name;
const VUE_APP_BASE_API = process.env.VUE_APP_BASE_API;
const VUE_APP_BASE_REWRITE_API = process.env.VUE_APP_BASE_REWRITE_API;
const VUE_APP_SERVER_URL = process.env.VUE_APP_SERVER_URL;
const AutoImport = require("unplugin-auto-import/webpack");
const Timestamp = new Date().getTime();
const path = require("path");
const resolve = (dir) => path.join(__dirname, dir);
module.exports = defineConfig({
transpileDependencies: true,
productionSourceMap: false,
publicPath: "./",
outputDir: name,
assetsDir: "assets",
chainWebpack: (config) => {
const oneOfsMap = config.module.rule("less").oneOfs.store;
oneOfsMap.forEach(item => {
item
.use("style-resources-loader")
.loader("style-resources-loader")
.options({
// or an array : ["./path/to/vars.less", "./path/to/mixins.less"] 这里的路径不能使用@,否则会报错
patterns: "./src/style/subApp.less"
})
.end()
});
config.plugin("html").tap((args) => {
args[0].title = "星芒运行态扩展应用";
return args;
});
config.resolve.alias
.set('/#/', resolve('types/'));
// svg图标加载
config.module
.rule("svg")
.exclude.add(path.join(__dirname, "src/icons/svg"))
.end();
config.module
.rule("icons") // 定义一个名叫 icons 的规则
.test(/\.svg$/) // 设置 icons 的匹配正则
.include.add(path.join(__dirname, "src/icons/svg")) // 设置当前规则的作用目录,只在当前目录下才执行当前规则
.end()
.use("svg-sprite") // 指定一个名叫 svg-sprite 的 loader 配置
.loader("svg-sprite-loader") // 该配置使用 svg-sprite-loader 作为处理 loader
.options({
// 该 svg-sprite-loader 的配置
symbolId: "icon-[name]",
})
.end();
},
css: {
loaderOptions: {
less: {
lessOptions: {
modifyVars: {
//这是配置css主题色
// "primary-color": "#347AE2",
// 'border-radius-base': '6px',
},
javascriptEnabled: true,
},
},
},
// 每次打包后生成的css携带时间戳
extract: {
filename: `css/[name].${Timestamp}.css`,
chunkFilename: `css/[name].${Timestamp}.css`,
},
},
devServer: {
port: 3333,
open: false,
headers: {
"Access-Control-Allow-Origin": "*",
},
historyApiFallback: true,
// 配置多个代理
proxy: {
[`^${VUE_APP_BASE_API}`]: {
target: VUE_APP_SERVER_URL,
changeOrigin: true,
// pathRewrite: {
// [`^${VUE_APP_BASE_API}`]: VUE_APP_BASE_REWRITE_API,
// },
pathRewrite: (path) => path.replace(/^\/api/, ""),
},
},
},
configureWebpack: {
output: {
library: `${name}-[name]`,
libraryTarget: "umd", // 把微应用打包成 umd 库格式
chunkLoadingGlobal: `webpackJsonp_${name}`,
},
plugins: [
new CompressionWebpackPlugin({
filename: '[path][base].gz',
algorithm: 'gzip',
test: productionGzipExtensions,
threshold: 10240,//大于10k的进行压缩
minRatio: 0.8,
}),
AutoImport({
imports: ["vue", "pinia", "vue-router"],
dts: true,
eslintrc: {
enabled: true,
globalsPropValue: "readonly",
},
}),
],
},
});