import { defineConfig } from "vite";
import vue from "@vitejs/plugin-vue";
import path from "path";
import { visualizer } from "rollup-plugin-visualizer";
import externalGlobals from "rollup-plugin-external-globals";
import AutoImport from "unplugin-auto-import/vite";
import Components from "unplugin-vue-components/vite";
import { ElementPlusResolver } from "unplugin-vue-components/resolvers";
// 自动导入cdn
import { createHtmlPlugin } from "vite-plugin-html";
// gzip
import viteCompression from "vite-plugin-compression";
const cdn = {
css: [
"https://cdn.jsdelivr.net/npm/element-plus@2.7.6/dist/index.min.css"
],
js: [
"https://unpkg.com/vue@3.2.45/dist/vue.global.prod.js",
"https://unpkg.com/vue-router@4.1.6",
"https://cdn.jsdelivr.net/npm/lodash@4.17.21/lodash.js",
"https://cdn.jsdelivr.net/npm/swiper@11.1.4/swiper-bundle.min.js",
"https://unpkg.com/axios@1.3.3/dist/axios.min.js",
"https://cdn.jsdelivr.net/npm/element-plus@2.7.6/dist/index.full.min.js"
],
};
export default defineConfig(({ mode }) => {
const isProduction = mode === "production";
return {
plugins: [
createHtmlPlugin({
inject: {
data: {
cdnCss: isProduction ? cdn.css : [],
cdnJs: isProduction ? cdn.js : [],
},
},
}),
viteCompression({
verbose: true, // 默认即可
disable: false, // 开启压缩(不禁用),默认即可
deleteOriginFile: false, // 删除源文件
threshold: 5120, // 压缩前最小文件大小
algorithm: "gzip", // 压缩算法
ext: ".gz", // 文件类型
}),
// AutoImport({
// resolvers: [ElementPlusResolver()],
// }),
// Components({
// resolvers: [ElementPlusResolver()],
// }),
vue(),
visualizer({
filename: "source.html", // 输出文件名
// open: true, // 是否自动打开浏览器查看
}),
// vue: 'Vue' --- vue为依赖包名 Vue为项目构建后的全局变量
{
...externalGlobals({
vue: "Vue",
lodash: "_",
swiper: "Swiper",
"vue-router": "VueRouter",
axios: "axios",
'element-plus': 'ElementPlus',
}),
enforce: "post",
apply: "build",
},
],
server: {
host: "0.0.0.0",
port: 7000,
proxy: {
"/base": {
target: "http://localhost:9999",
changeOrigin: true,
ws: true,
rewrite: (path) => path.replace(new RegExp(`^/base`), ""),
},
},
},
resolve: {
//设置路径别名
alias: {
"@": path.resolve(__dirname, "./src"),
},
},
css: {
preprocessorOptions: {
scss: {
additionalData: `$injectedColor: orange;`,
},
},
},
build: {
terserOptions: {
compress: {
//生产环境时移除console
drop_console: process.env.NODE_ENV === "production" ? true : false,
drop_debugger: process.env.NODE_ENV === "production" ? true : false,
},
},
// 告诉打包工具 在external配置的 都是外部依赖项 不需要打包
external: [
"vue",
"vue-router",
"lodash",
"swiper",
"axios",
"element-plus",
],
// plugins: [
//
// // 避免打包和生产模式运行出错 在这里声明公共模块
// externalGlobals({
// vue: "Vue",
// lodash: "_",
// "vue-router": "VueRouter",
// }),
// ],
rollupOptions: {
output: {
chunkFileNames: "js/[name]-[hash].js",
entryFileNames: "js/[name]-[hash].js",
assetFileNames: "[ext]/[name]-[hash].[ext]",
manualChunks(id) {
if (id.includes("node_modules")) {
if (id.includes("node_modules/.pnpm")) return;
return id
.toString()
.split("node_modules/")[1]
.split("/")[0]
.toString();
}
},
},
},
reportCompressedSize: false,
sourcemap: false, // 这个生产环境一定要关闭,不然打包的产物会很大
},
};
});
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<% for (const i of cdnCss) { %>
<link href="<%= i %>" rel="stylesheet" />
<% } %>
<% for (const i of cdnJs) { %>
<script src="<%= i %>" defer></script>
<% } %>
<!-- <script src="https://unpkg.com/vue@3.2.45/dist/vue.global.prod.js"></script>
<script src="https://unpkg.com/vue-router@4.1.6"></script>
<script src="https://cdn.jsdelivr.net/npm/lodash@4.17.21/lodash.js"></script>
<script src="https://cdn.jsdelivr.net/npm/swiper@11.1.4/swiper-bundle.min.js"></script>
<script src="https://unpkg.com/axios@1.3.3/dist/axios.min.js"></script> -->
<!-- cnd外链只针对全局引入注册el-plus有效 -->
<!-- <script src="https://cdn.jsdelivr.net/npm/element-plus@2.7.4/dist/index.full.min.js"></script>
<link href="https://cdn.jsdelivr.net/npm/element-plus@2.7.4/dist/index.min.css" rel="stylesheet"> -->
<link rel="icon" type="image/svg+xml" href="/vite.svg" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>cx_shop</title>
<style>
.spinner {
font-size: 35px;
position: relative;
display: inline-block;
width: 1em;
height: 1em;
}
.spinner.center {
position: absolute;
left: 0;
right: 0;
top: 0;
bottom: 0;
margin: auto;
}
.spinner .spinner-blade {
position: absolute;
left: 0.4629em;
bottom: 0;
width: 0.074em;
height: 0.2777em;
border-radius: 0.0555em;
background-color: transparent;
-webkit-transform-origin: center -0.2222em;
-ms-transform-origin: center -0.2222em;
transform-origin: center -0.2222em;
animation: spinner-fade9234 1s infinite linear;
}
.spinner .spinner-blade:nth-child(1) {
-webkit-animation-delay: 0s;
animation-delay: 0s;
-webkit-transform: rotate(0deg);
-ms-transform: rotate(0deg);
transform: rotate(0deg);
}
.spinner .spinner-blade:nth-child(2) {
-webkit-animation-delay: 0.083s;
animation-delay: 0.083s;
-webkit-transform: rotate(30deg);
-ms-transform: rotate(30deg);
transform: rotate(30deg);
}
.spinner .spinner-blade:nth-child(3) {
-webkit-animation-delay: 0.166s;
animation-delay: 0.166s;
-webkit-transform: rotate(60deg);
-ms-transform: rotate(60deg);
transform: rotate(60deg);
}
.spinner .spinner-blade:nth-child(4) {
-webkit-animation-delay: 0.249s;
animation-delay: 0.249s;
-webkit-transform: rotate(90deg);
-ms-transform: rotate(90deg);
transform: rotate(90deg);
}
.spinner .spinner-blade:nth-child(5) {
-webkit-animation-delay: 0.332s;
animation-delay: 0.332s;
-webkit-transform: rotate(120deg);
-ms-transform: rotate(120deg);
transform: rotate(120deg);
}
.spinner .spinner-blade:nth-child(6) {
-webkit-animation-delay: 0.415s;
animation-delay: 0.415s;
-webkit-transform: rotate(150deg);
-ms-transform: rotate(150deg);
transform: rotate(150deg);
}
.spinner .spinner-blade:nth-child(7) {
-webkit-animation-delay: 0.498s;
animation-delay: 0.498s;
-webkit-transform: rotate(180deg);
-ms-transform: rotate(180deg);
transform: rotate(180deg);
}
.spinner .spinner-blade:nth-child(8) {
-webkit-animation-delay: 0.581s;
animation-delay: 0.581s;
-webkit-transform: rotate(210deg);
-ms-transform: rotate(210deg);
transform: rotate(210deg);
}
.spinner .spinner-blade:nth-child(9) {
-webkit-animation-delay: 0.664s;
animation-delay: 0.664s;
-webkit-transform: rotate(240deg);
-ms-transform: rotate(240deg);
transform: rotate(240deg);
}
.spinner .spinner-blade:nth-child(10) {
-webkit-animation-delay: 0.747s;
animation-delay: 0.747s;
-webkit-transform: rotate(270deg);
-ms-transform: rotate(270deg);
transform: rotate(270deg);
}
.spinner .spinner-blade:nth-child(11) {
-webkit-animation-delay: 0.83s;
animation-delay: 0.83s;
-webkit-transform: rotate(300deg);
-ms-transform: rotate(300deg);
transform: rotate(300deg);
}
.spinner .spinner-blade:nth-child(12) {
-webkit-animation-delay: 0.913s;
animation-delay: 0.913s;
-webkit-transform: rotate(330deg);
-ms-transform: rotate(330deg);
transform: rotate(330deg);
}
@keyframes spinner-fade9234 {
0% {
background-color: #69717d;
}
100% {
background-color: transparent;
}
}
</style>
</head>
<body>
<div id="app">
<div class="spinner center">
<div class="spinner-blade"></div>
<div class="spinner-blade"></div>
<div class="spinner-blade"></div>
<div class="spinner-blade"></div>
<div class="spinner-blade"></div>
<div class="spinner-blade"></div>
<div class="spinner-blade"></div>
<div class="spinner-blade"></div>
<div class="spinner-blade"></div>
<div class="spinner-blade"></div>
<div class="spinner-blade"></div>
<div class="spinner-blade"></div>
</div>
</div>
<script type="module" src="/src/main.js"></script>
</body>
</html>
main.js
import ElementPlus from 'element-plus'
import 'element-plus/dist/index.css'
````
const app = createApp(App);
app.use(ElementPlus)
开发依赖
"devDependencies": {
"@vitejs/plugin-vue": "^5.0.4",
"rollup-plugin-external-globals": "^0.10.0",
"rollup-plugin-visualizer": "^5.12.0",
"terser": "^5.31.0",
"unplugin-auto-import": "^0.17.6",
"unplugin-vue-components": "^0.27.0",
"vite": "^5.2.0",
"vite-plugin-compression": "^0.5.1",
"vite-plugin-html": "^3.2.2"
}