🐛 build文件确实
This commit is contained in:
parent
f95dc4d947
commit
42f1a7edfe
|
@ -61,7 +61,6 @@ lerna-debug.log*
|
||||||
/dist/
|
/dist/
|
||||||
/nbdist/
|
/nbdist/
|
||||||
/.nb-gradle/
|
/.nb-gradle/
|
||||||
build/
|
|
||||||
!**/src/main/**/build/
|
!**/src/main/**/build/
|
||||||
!**/src/test/**/build/
|
!**/src/test/**/build/
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,53 @@
|
||||||
|
import type { BuildOptions } from 'vite';
|
||||||
|
|
||||||
|
import { pathResolve } from './utils';
|
||||||
|
|
||||||
|
export const buildEnv = (): BuildOptions => {
|
||||||
|
return {
|
||||||
|
target: 'es2015',
|
||||||
|
assetsInlineLimit: 20000,
|
||||||
|
// 构建输出的目录,默认值为"dist"
|
||||||
|
outDir: 'docker/dist',
|
||||||
|
// 用于指定使用的代码压缩工具。在这里,minify 被设置为 'terser',表示使用 Terser 进行代码压缩。默认值terser
|
||||||
|
// esbuild 打包更快,但是不能去除 console.log,terser打包慢,但能去除 console.log
|
||||||
|
minify: 'terser', // "esbuild"
|
||||||
|
// 用于配置 Terser 的选项
|
||||||
|
terserOptions: {
|
||||||
|
// 用于配置压缩选项
|
||||||
|
compress: {
|
||||||
|
drop_console: true, // 是否删除代码中的 console 语句, 默认值false
|
||||||
|
drop_debugger: true, // 是否删除代码中的 debugger 语句, 默认值false
|
||||||
|
},
|
||||||
|
},
|
||||||
|
// 禁用 gzip 压缩大小报告,可略微减少打包时间
|
||||||
|
reportCompressedSize: false,
|
||||||
|
// 用于指定是否生成源映射文件。源映射文件可以帮助调试和定位源代码中的错误。当设置为false时,构建过程不会生成源映射文件
|
||||||
|
sourcemap: false,
|
||||||
|
// 用于配置 CommonJS 模块的选项
|
||||||
|
commonjsOptions: {
|
||||||
|
// 用于指定是否忽略 CommonJS 模块中的 try-catch 语句。当设置为false时,构建过程会保留 CommonJS 模块中的 try-catch 语句
|
||||||
|
ignoreTryCatch: false,
|
||||||
|
},
|
||||||
|
// 规定触发警告的 chunk 大小, 当某个代码分块的大小超过该限制时,Vite 会发出警告
|
||||||
|
chunkSizeWarningLimit: 2000,
|
||||||
|
rollupOptions: {
|
||||||
|
external: ['md-editor-v3', 'echarts'],
|
||||||
|
input: {
|
||||||
|
// @ts-ignore
|
||||||
|
index: pathResolve('../index.html', import.meta.url),
|
||||||
|
},
|
||||||
|
// 静态资源分类打包
|
||||||
|
output: {
|
||||||
|
chunkFileNames: 'static/js/[name]-[hash].js',
|
||||||
|
entryFileNames: 'static/js/[name]-[hash].js',
|
||||||
|
assetFileNames: 'static/[ext]/[name]-[hash].[ext]',
|
||||||
|
manualChunks: (id) => {
|
||||||
|
// 如果是包含在包中则打包成 vendor
|
||||||
|
if (id.includes('node_modules')) {
|
||||||
|
return `vendor`;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
};
|
|
@ -0,0 +1,47 @@
|
||||||
|
import { Plugin as importToCDN } from 'vite-plugin-cdn-import';
|
||||||
|
|
||||||
|
import { wrapperEnv } from './utils';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description 打包时采用`cdn`模式,仅限外网使用(默认不采用,如果需要采用cdn模式,请在 .env.production 文件,将 VITE_CDN 设置成true)
|
||||||
|
* 平台采用国内cdn:https://www.bootcdn.cn,当然你也可以选择 https://unpkg.com 或者 https://www.jsdelivr.com
|
||||||
|
* 注意:上面提到的仅限外网使用也不是完全肯定的,如果你们公司内网部署的有相关js、css文件,也可以将下面配置对应改一下,整一套内网版cdn
|
||||||
|
*/
|
||||||
|
export const cdn = importToCDN({
|
||||||
|
//(prodUrl解释: name: 对应下面modules的name,version: 自动读取本地package.json中dependencies依赖中对应包的版本号,path: 对应下面modules的path,当然也可写完整路径,会替换prodUrl)
|
||||||
|
// prodUrl: 'https://cdn.bootcdn.net/ajax/libs/{name}/{version}/{path}',
|
||||||
|
prodUrl: 'https://unpkg.com/{name}@{version}/{path}',
|
||||||
|
modules: [
|
||||||
|
{
|
||||||
|
name: 'vue',
|
||||||
|
var: 'Vue',
|
||||||
|
path: 'dist/vue.global.prod.js',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'vue-router',
|
||||||
|
var: 'VueRouter',
|
||||||
|
path: 'dist/vue-router.global.js',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'pinia',
|
||||||
|
var: 'Pinia',
|
||||||
|
path: 'dist/pinia.iife.js',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'axios',
|
||||||
|
var: 'axios',
|
||||||
|
path: 'dist/axios.min.js',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'dayjs',
|
||||||
|
var: 'dayjs',
|
||||||
|
path: 'dayjs.min.js',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
});
|
||||||
|
|
||||||
|
/* 是否使用CDN加速 */
|
||||||
|
export const useCDN = (mode) => {
|
||||||
|
const env = wrapperEnv(mode, 'VITE');
|
||||||
|
return env.VITE_CDN ? cdn : null;
|
||||||
|
};
|
|
@ -0,0 +1,12 @@
|
||||||
|
import type { CSSOptions } from 'vite';
|
||||||
|
|
||||||
|
|
||||||
|
export const css = (mode: string): CSSOptions => {
|
||||||
|
return {
|
||||||
|
preprocessorOptions: {
|
||||||
|
scss: {
|
||||||
|
additionalData: `@use "@/assets/styles/minix/sidebar" as *;`,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
};
|
|
@ -0,0 +1,14 @@
|
||||||
|
import dayjs from 'dayjs';
|
||||||
|
|
||||||
|
import { dependencies, devDependencies, engines, name, version } from '../package.json';
|
||||||
|
|
||||||
|
const __APP_INFO__ = {
|
||||||
|
pkg: { name, version, engines, dependencies, devDependencies },
|
||||||
|
lastBuildTime: dayjs(new Date()).format('YYYY-MM-DD HH:mm:ss'),
|
||||||
|
};
|
||||||
|
|
||||||
|
export const define = () => {
|
||||||
|
return {
|
||||||
|
__APP_INFO__: JSON.stringify(__APP_INFO__),
|
||||||
|
};
|
||||||
|
};
|
|
@ -0,0 +1,58 @@
|
||||||
|
import boxen, { type Options as BoxenOptions } from 'boxen';
|
||||||
|
import dayjs, { type Dayjs } from 'dayjs';
|
||||||
|
import duration from 'dayjs/plugin/duration';
|
||||||
|
import gradientString from 'gradient-string';
|
||||||
|
|
||||||
|
import { logOutputSize, wrapperEnv } from './utils';
|
||||||
|
|
||||||
|
dayjs.extend(duration);
|
||||||
|
|
||||||
|
const boxenOptions: BoxenOptions = {
|
||||||
|
padding: 0.94,
|
||||||
|
borderColor: 'cyan',
|
||||||
|
borderStyle: 'round',
|
||||||
|
textAlignment: 'left',
|
||||||
|
};
|
||||||
|
|
||||||
|
/* 输出日志信息 */
|
||||||
|
const printLogMessage = (VITE_PORT: number) => {
|
||||||
|
return gradientString('cyan', 'magenta').multiline(
|
||||||
|
`欢迎使用此项目,项目访问地址如下:
|
||||||
|
http://localhost:${VITE_PORT}`
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export const viteConsoleLog = (mode: string) => {
|
||||||
|
const { VITE_PORT } = wrapperEnv(mode);
|
||||||
|
|
||||||
|
let config: { command: string };
|
||||||
|
let startTime: Dayjs;
|
||||||
|
let endTime: Dayjs;
|
||||||
|
return {
|
||||||
|
name: 'vite:buildInfo',
|
||||||
|
configResolved(resolvedConfig) {
|
||||||
|
config = resolvedConfig;
|
||||||
|
},
|
||||||
|
buildStart() {
|
||||||
|
console.log(boxen(printLogMessage(VITE_PORT), boxenOptions));
|
||||||
|
if (config.command === 'build') {
|
||||||
|
startTime = dayjs(new Date());
|
||||||
|
}
|
||||||
|
},
|
||||||
|
closeBundle() {
|
||||||
|
if (config.command === 'build') {
|
||||||
|
endTime = dayjs(new Date());
|
||||||
|
const format = dayjs.duration(endTime.diff(startTime)).format('mm分ss秒');
|
||||||
|
|
||||||
|
console.log(
|
||||||
|
boxen(
|
||||||
|
gradientString('cyan', 'magenta').multiline(
|
||||||
|
`🎉 恭喜打包完成(总用时${format})打包大小(${logOutputSize()})`
|
||||||
|
),
|
||||||
|
boxenOptions
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
};
|
||||||
|
};
|
|
@ -0,0 +1,14 @@
|
||||||
|
/**
|
||||||
|
* 此文件作用于 `vite.config.ts` 的 `optimizeDeps.include` 依赖预构建配置项
|
||||||
|
* 依赖预构建,`vite` 启动时会将下面 include 里的模块,编译成 esm 格式并缓存到 node_modules/.vite 文件夹,页面加载到对应模块时如果浏览器有缓存就读取浏览器缓存,如果没有会读取本地缓存并按需加载
|
||||||
|
* 尤其当您禁用浏览器缓存时(这种情况只应该发生在调试阶段)必须将对应模块加入到 include里,否则会遇到开发环境切换页面卡顿的问题(vite 会认为它是一个新的依赖包会重新加载并强制刷新页面),因为它既无法使用浏览器缓存,又没有在本地 node_modules/.vite 里缓存
|
||||||
|
* 温馨提示:如果您使用的第三方库是全局引入,也就是引入到 src/main.ts 文件里,就不需要再添加到 include 里了,因为 vite 会自动将它们缓存到 node_modules/.vite
|
||||||
|
*/
|
||||||
|
const include = ['vue', 'vue-router', 'dayjs', 'axios', 'pinia', 'vue-types', 'js-cookie'];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 在预构建中强制排除的依赖项
|
||||||
|
*/
|
||||||
|
const exclude: string[] = [];
|
||||||
|
|
||||||
|
export { exclude, include };
|
|
@ -0,0 +1,45 @@
|
||||||
|
import UnoCssIcons from '@unocss/preset-icons';
|
||||||
|
import vue from '@vitejs/plugin-vue';
|
||||||
|
import vueJsx from '@vitejs/plugin-vue-jsx';
|
||||||
|
import { presetIcons } from 'unocss';
|
||||||
|
import UnoCSS from 'unocss/vite';
|
||||||
|
import type { PluginOption } from 'vite';
|
||||||
|
import removeConsole from 'vite-plugin-remove-console';
|
||||||
|
import Inspector from 'vite-plugin-vue-inspector';
|
||||||
|
|
||||||
|
import { useCDN } from './cdn';
|
||||||
|
import { viteConsoleLog } from './info';
|
||||||
|
import { compressPack, report } from './utils';
|
||||||
|
|
||||||
|
export const plugins = (mode: string): PluginOption[] => {
|
||||||
|
return [
|
||||||
|
vue(),
|
||||||
|
vueJsx(),
|
||||||
|
Inspector(),
|
||||||
|
report(),
|
||||||
|
removeConsole(),
|
||||||
|
useCDN(mode),
|
||||||
|
viteConsoleLog(mode),
|
||||||
|
UnoCSS({
|
||||||
|
hmrTopLevelAwait: false,
|
||||||
|
inspector: true, // 控制台是否打印 UnoCSS inspector
|
||||||
|
presets: [
|
||||||
|
presetIcons({
|
||||||
|
prefix: '',
|
||||||
|
extraProperties: {
|
||||||
|
display: 'inline-block',
|
||||||
|
'vertical-align': 'middle',
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
UnoCssIcons({
|
||||||
|
prefix: '',
|
||||||
|
extraProperties: {
|
||||||
|
display: 'inline-block',
|
||||||
|
'vertical-align': 'middle',
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
],
|
||||||
|
}),
|
||||||
|
compressPack(mode),
|
||||||
|
];
|
||||||
|
};
|
|
@ -0,0 +1,9 @@
|
||||||
|
import { pathResolve } from './utils';
|
||||||
|
|
||||||
|
export const resolve = () => {
|
||||||
|
return {
|
||||||
|
alias: {
|
||||||
|
'@': pathResolve('../src'),
|
||||||
|
},
|
||||||
|
};
|
||||||
|
};
|
|
@ -0,0 +1,34 @@
|
||||||
|
import type { ServerOptions } from 'vite';
|
||||||
|
|
||||||
|
import { wrapperEnv } from './utils';
|
||||||
|
|
||||||
|
/* 开发服务配置 */
|
||||||
|
export const server = (mode: string) => {
|
||||||
|
const { VITE_PORT, VITE_APP_URL, VITE_STRICT_PORT } = wrapperEnv(mode);
|
||||||
|
|
||||||
|
const options: ServerOptions = {
|
||||||
|
strictPort: VITE_STRICT_PORT,
|
||||||
|
port: VITE_PORT,
|
||||||
|
host: '0.0.0.0',
|
||||||
|
open: true,
|
||||||
|
cors: true,
|
||||||
|
proxy: {
|
||||||
|
'/api': {
|
||||||
|
target: VITE_APP_URL,
|
||||||
|
changeOrigin: true,
|
||||||
|
rewrite: (path: string) => path.replace(/^\/api/, '/api'),
|
||||||
|
},
|
||||||
|
'/mock': {
|
||||||
|
target: VITE_APP_URL,
|
||||||
|
changeOrigin: true,
|
||||||
|
rewrite: (path: string) => path.replace(/^\/mock/, '/mock'),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
// 预热文件以提前转换和缓存结果,降低启动期间的初始页面加载时长并防止转换瀑布
|
||||||
|
warmup: {
|
||||||
|
clientFiles: ['./index.html', './src/{views,components}/*'],
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
return options;
|
||||||
|
};
|
|
@ -0,0 +1,118 @@
|
||||||
|
import { dirname, resolve } from 'node:path';
|
||||||
|
import { fileURLToPath } from 'node:url';
|
||||||
|
|
||||||
|
import fs from 'fs';
|
||||||
|
import path from 'path';
|
||||||
|
import { visualizer } from 'rollup-plugin-visualizer';
|
||||||
|
import { loadEnv } from 'vite';
|
||||||
|
import viteCompression from 'vite-plugin-compression';
|
||||||
|
|
||||||
|
import { buildEnv } from './buildEnv';
|
||||||
|
|
||||||
|
export const root: string = process.cwd();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description 根据可选的路径片段生成一个新的绝对路径
|
||||||
|
* @param dir 路径片段,默认`build`
|
||||||
|
* @param metaUrl 模块的完整`url`,如果在`build`目录外调用必传`import.meta.url`
|
||||||
|
*/
|
||||||
|
// @ts-ignore
|
||||||
|
export const pathResolve = (dir = '.', metaUrl = import.meta.url) => {
|
||||||
|
// 当前文件目录的绝对路径
|
||||||
|
const currentFileDir = dirname(fileURLToPath(metaUrl));
|
||||||
|
// build 目录的绝对路径
|
||||||
|
const buildDir = resolve(currentFileDir, 'build');
|
||||||
|
// 解析的绝对路径
|
||||||
|
const resolvedPath = resolve(currentFileDir, dir);
|
||||||
|
// 检查解析的绝对路径是否在 build 目录内
|
||||||
|
if (resolvedPath.startsWith(buildDir)) {
|
||||||
|
// 在 build 目录内,返回当前文件路径
|
||||||
|
return fileURLToPath(metaUrl);
|
||||||
|
}
|
||||||
|
// 不在 build 目录内,返回解析后的绝对路径
|
||||||
|
return resolvedPath;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 封装环境变量配置
|
||||||
|
* @param mode 当前模式
|
||||||
|
* @param prefix 需要过滤的前缀
|
||||||
|
* @link 参考:https://cn.vite.dev/config/#using-environment-variables-in-config
|
||||||
|
*/
|
||||||
|
// @ts-ignore
|
||||||
|
export const wrapperEnv = (mode: string, prefix: string = ''): ViteEnv => {
|
||||||
|
const env: any = loadEnv(mode, root, prefix);
|
||||||
|
|
||||||
|
// 将变量转换指定类型
|
||||||
|
for (const envName of Object.keys(env)) {
|
||||||
|
let realName: string | boolean | number = env[envName].replace(/\\n/g, '\n');
|
||||||
|
realName = realName === 'true' ? true : realName === 'false' ? false : realName;
|
||||||
|
|
||||||
|
if (envName === 'VITE_PORT') {
|
||||||
|
realName = Number(realName);
|
||||||
|
}
|
||||||
|
env[envName] = realName;
|
||||||
|
// @ts-ignore
|
||||||
|
process.env[envName] = realName;
|
||||||
|
}
|
||||||
|
return env;
|
||||||
|
};
|
||||||
|
|
||||||
|
/* 打包分析 */
|
||||||
|
export const report = () => {
|
||||||
|
const lifecycle = process.env.npm_lifecycle_event;
|
||||||
|
return lifecycle === 'report'
|
||||||
|
? visualizer({ open: true, brotliSize: true, filename: 'report.html' })
|
||||||
|
: (null as any);
|
||||||
|
};
|
||||||
|
|
||||||
|
/* 启用gzip压缩 */
|
||||||
|
export const compressPack = (mode: string) => {
|
||||||
|
const { VITE_COMPRESSION } = wrapperEnv(mode);
|
||||||
|
|
||||||
|
return VITE_COMPRESSION == 'gzip' ? viteCompression({ threshold: 1024000 }) : null;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 计算打包后文件夹大小
|
||||||
|
* @returns
|
||||||
|
*/
|
||||||
|
export const logOutputSize = (): string => {
|
||||||
|
const outDir = `../${buildEnv().outDir}`;
|
||||||
|
|
||||||
|
function convertSize(size: number) {
|
||||||
|
const units: Array<string> = ['byte', 'KB', 'MB', 'GB'];
|
||||||
|
|
||||||
|
// 输入的单位是否存在
|
||||||
|
let index = 0;
|
||||||
|
|
||||||
|
while (size >= 1024) {
|
||||||
|
size /= 1024;
|
||||||
|
index++;
|
||||||
|
}
|
||||||
|
|
||||||
|
return `${size.toFixed(2)} ${units[index]}`;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 计算文件夹字节大小
|
||||||
|
function getFolderSize(folderPath: string) {
|
||||||
|
let size = 0;
|
||||||
|
|
||||||
|
fs.readdirSync(folderPath).forEach((fileName: string) => {
|
||||||
|
const filePath = path.join(folderPath, fileName);
|
||||||
|
const stats = fs.statSync(filePath);
|
||||||
|
|
||||||
|
if (stats.isFile()) {
|
||||||
|
size += stats.size;
|
||||||
|
} else if (stats.isDirectory()) {
|
||||||
|
size += getFolderSize(filePath);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
return size;
|
||||||
|
}
|
||||||
|
|
||||||
|
const folderSize = getFolderSize(path.resolve(__dirname, outDir));
|
||||||
|
|
||||||
|
return convertSize(folderSize);
|
||||||
|
};
|
Loading…
Reference in New Issue