多页面配置
目录结构
vite-vue3
│
├─ config
│ ├─ base.ts
│ └─ index.ts
├─ dist
├─ node_modules
├─ plugins
│ └─ inject-html-plugin.js
├─ public
├─ src
│ ├─ assets
│ ├─ components
│ ├─ pages
│ │ ├─ simpleTest
│ │ │ ├─ api
│ │ │ ├─ assets
│ │ │ ├─ components
│ │ │ ├─ router
│ │ │ ├─ stores
│ │ │ ├─ views
│ │ │ ├─ App.vue
│ │ │ ├─ index.html
│ │ │ └─ main.ts
│ │ └─ index.html
│ ├─ utils
│ └─ global.d.ts
│
└─ vite.config.ts
基础配置 base.ts
const path = require('path');
export default {
// 多页配置
isMultiplePage: true,
// 文件目录
assetsRoot: path.resolve(__dirname, '../src'),
// 生成目录
buildRoot: path.resolve(__dirname, '../dist'),
// 生成路径
publicPath: '/',
// 开启 includeProject
isInclude: true,
// 会监听的项目
includeProject: [
/simpleTest/
],
// 本地开发端口
port: 8007,
// 本地开发代理
proxy: {}
}
build配置 index.ts
const
path = require('path'),
Glob = require('glob').Glob,
base = require('./base');
const fs = require('fs');
const { EXCLUDED_BUILD_PAGE_REGEXPS=[], includeProject, isInclude, assetsRoot, buildRoot} = base.default;
function getPath(...args: string[]) {
return path.join(assetsRoot, ...args);
}
// build
const build = {
outDir: buildRoot,// 指定输出路径(相对于 项目根目录)
sourcemap: false, // 构建后是否生成 source map 文件
chunkSizeWarningLimit: 1500, // 规定触发警告的 chunk(文件块) 大小
minify: 'esbuild',
rollupOptions: { // 自定义底层的 Rollup 打包配置
input: getEntrySetting(),
output: {
entryFileNames: "assets/js/[name]-[hash].js",
chunkFileNames: "assets/js/[name]-[hash].js",
assetFileNames: "assets/[ext]/[name]-[hash].[ext]",
compact: true,
// 文档 https://cn.rollupjs.org/configuration-options/#output-manualchunks
manualChunks: (id: string) => {
if(id.includes("node_modules")) {
// return id.toString().split('node_modules/')[1].split('/')[0].toString(); // 拆分多个vendors
return 'vendor'; // 合成一个vendors
}
}
}
},
emptyOutDir: true,
target: 'es2015',
}
// getEntrySetting 处理多个入口文件
function getEntrySetting() {
const result: { [x: string]: any; } = {};
new Glob('!(_)*/**/!(_)*.html', {
cwd: getPath('pages'),
sync: true
}).found.forEach((file: string) => {
const pageName = file.split('/').slice(0, -1).join('/')
let entryUrl;
if(isInclude){
if (includeProject.filter((regexp: { test: (arg0: any) => any; }) => regexp.test(pageName)).length == 0) return;
}else{
if (EXCLUDED_BUILD_PAGE_REGEXPS.filter((regexp: { test: (arg0: any) => any; }) => regexp.test(pageName)).length > 0) return;
}
const tempUrl = `src/pages/${pageName}`
const url = path.join(process.cwd(),tempUrl,'index.html');
if(fs.existsSync(url)){ //增加ts入口
entryUrl = getPath('pages', pageName, 'index.html');
}else{
entryUrl = getPath('pages', pageName, 'index.html');
}
result[pageName] = entryUrl;
});
return result;
}
const css = {
postcss: {
plugins: [
autoprefixer({
overrideBrowserslist: ['Android 4.1', 'iOS 7.1', 'Chrome > 31', 'ff > 31', 'ie >= 8'],
}),
// 兼容pc,不至于过大 a, /*no*/ 加这个不好使,
// b, 也不好使 https://github.com/gaofant101/blog/issues/15
// c, 使用selectorBlackList解决
postCssPxToRem({
// 自适应,px>rem转换
rootValue: 37.5, // 75表示750设计稿,37.5表示375设计稿
propList: ['*'], // 需要转换的属性,这里选择全部都进行转换
selectorBlackList: ['norem'], // 过滤掉norem-开头的class,不进行rem转换
}),
postCssRTLCSS(), // 参考 https://juejin.cn/post/6989055383486758919
],
},
preprocessorOptions: {
less: {
// 一些配置项
}
}
}
const server = {
host: '0.0.0.0', // 指定服务器应该监听哪个 IP 地址
port: base.default.port, // 端口
strictPort: false, // 若端口已被占用,尝试下移一格端口
open: false,
proxy: base.default.proxy,
}
export default {
entry: getEntrySetting(),
build: build,
baseConfig: base.default,
devServer: server,
css: css
};
vite.config.ts
import { fileURLToPath, URL } from 'node:url'
import { defineConfig, loadEnv } from 'vite'
import vue from '@vitejs/plugin-vue'
import vueJsx from '@vitejs/plugin-vue-jsx'
import eslintPlugin from 'vite-plugin-eslint' //导入包
import config from './config/index'
import legacy from '@vitejs/plugin-legacy'
// 代码体积优化 https://blog.csdn.net/qq_41581588/article/details/132023477
// 代码体积分析
import { visualizer } from 'rollup-plugin-visualizer'
// https://vitejs.dev/config/
export default defineConfig(({command, mode}) => {
const env = loadEnv(mode, process.cwd())
// console.log('env', env)
return {
// root: 'src/pages', // 不能改成这个读取.env 文件有问题。import.meta.env 访问需加 /src/pages/xxx
base: config.baseConfig.publicPath,
define: { 'process.env': {
...env
} },
plugins: [
visualizer({ open: true }),
vue(),
vueJsx(),
// 增加下面的配置项,这样在运行时就能检查eslint规范
eslintPlugin({
include: ['src/**/*.js', 'src/**/*.vue', 'src/*.js', 'src/*.vue'],
exclude: ['./node_modules/**', './src/types/**'],
cache: false
}),
// https://juejin.cn/post/7114586736201580575
legacy({
targets: ['defaults', 'chrome 42', 'safari 11.0', 'ios >= 9', 'android >= 4.2'],
additionalLegacyPolyfills: ['regenerator-runtime/runtime'],
renderLegacyChunks: true,
modernPolyfills: ['es.global-this'], // 解决浏览器端 globalThis is not defined 报错
polyfills: [
'es.symbol',
'es.promise',
'es.promise.finally',
'es/map',
'es/set',
'es.array.filter',
'es.array.for-each',
'es.array.flat-map',
'es.object.define-properties',
'es.object.define-property',
'es.object.get-own-property-descriptor',
'es.object.get-own-property-descriptors',
'es.object.keys',
'es.object.to-string',
'web.dom-collections.for-each',
'esnext.global-this',
'esnext.string.match-all'
]
}),
],
resolve: {
alias: {
'@': fileURLToPath(new URL('./src', import.meta.url))
}
},
css: config.css,
server: config.devServer,
build: {
...config.build
}
}
})
优化
参考: mp.weixin.qq.com/s/GYtd3k0JX…
将公共文件提取出来,cdn引入
// 第一步:提取
import externalGlobals from 'rollup-plugin-external-globals'//CDN加载
build:{
rollupOptions: {
external: ['vue', 'vue-router',, 'xxx-base-common'],
plugins: [
externalGlobals({
vue: 'Vue',
'vue-router': 'VueRouter',
'xxx-base-common': 'xxxBaseCommon'
})
]
}
}
// 第二步: 引入
// 自定义插件,导入cdn transformIndexHtml(html) 根据标签直接替换
// inject-html-plugin.js
export default function injectHtmlPlugin(options) {
return {
name: 'inject-html-plugin',
transformIndexHtml(html) {
html = html.replace(
'<vuescript></vuescript>',
`
<script src="https://cdn.jsdelivr.net/npm/vue@3.3.4/dist/vue.global.min.js"></script>
`
);
html = html.replace(
'<vuerouterscript></vuerouterscript>',
`
<script src="https://unpkg.com/vue-router@4.2.4/dist/vue-router.global.js"></script>
`
);
return html;
}
};
}
// 使用
import injectHtmlPlugin from './plugins/inject-html-plugin.js';
plugins: [
injectHtmlPlugin(),
]