当 Element UI 通过 CDN 全量引入时(<script src="...element-ui/lib/index.js"></script>
),它会尝试使用全局的 Vue
对象来注册组件和指令。如果 Vue
不是通过 CDN 挂载到全局(window.Vue
),而是通过模块化方式(如 import Vue from 'vue'
)引入的,那么 Element UI 就找不到 Vue
,导致组件无法注册,页面上会出现 Unknown custom element
错误。
开发环境:都通过 npm
模块引入,正常 import
生产环境:Vue
和 Element UI
都通过 CDN 引入, 提高网页响应速度
步骤一:安装 Element UI(开发环境使用)
npm install element-ui
📄 步骤二:配置 vue.config.js
在项目根目录创建或修改 vue.config.js
:
const { defineConfig } = require('@vue/cli-service')
const isProd = process.env.NODE_ENV === 'production';
module.exports = defineConfig({
transpileDependencies: true,
configureWebpack: config => {
if (isProd) {
config.externals = {
'vue': 'Vue',
'vuex': 'Vuex',
'vue-router': 'VueRouter',
'element-ui': 'ELEMENT'
};
}
}
})
✅
externals
仅在生产构建时生效。
📄 步骤三:修改 main.js
(不需要改动, 按全局引入element ui)
import Vue from 'vue'
import App from './App.vue'
import router from './router'
import store from './store'
import ElementUI from 'element-ui';
import 'element-ui/lib/theme-chalk/index.css';
Vue.use(ElementUI);
Vue.config.productionTip = false
new Vue({
router,
store,
render: h => h(App)
}).$mount('#app')
✅ 开发环境:正常引入
✅ 生产环境:打包时候,会根据vue.config.js配置,跳过配置的文件
📄 步骤四:修改 public/index.html
在 </head>
前添加 CDN 引入(只在生产环境生效):
<!DOCTYPE html>
<html lang="">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width,initial-scale=1.0">
<link rel="icon" href="<%= BASE_URL %>favicon.ico">
<title><%= htmlWebpackPlugin.options.title %></title>
<!-- 生产环境且启用CDN时才加载CSS -->
<% if (process.env.NODE_ENV === 'production') { %>
<link rel="stylesheet" href="https://unpkg.com/element-ui/lib/theme-chalk/index.css">
<% } %>
</head>
<body>
<noscript>
<strong>We're sorry but <%= htmlWebpackPlugin.options.title %> doesn't work properly without JavaScript enabled. Please enable it to continue.</strong>
</noscript>
<div id="app"></div>
<!-- built files will be auto injected -->
<% if (process.env.NODE_ENV === 'production') { %>
<!-- Vue 必须最先引入 -->
<script src="https://unpkg.com/vue@2.7.16/dist/vue.min.js"></script>
<!-- Vuex -->
<script src="https://unpkg.com/vuex@3.6.2/dist/vuex.min.js"></script>
<!-- Vue Router -->
<script src="https://unpkg.com/vue-router@3.6.5/dist/vue-router.min.js"></script>
<!-- Element UI -->
<script src="https://unpkg.com/element-ui@2.15.14/lib/index.js"></script>
<% } %>
</body>
</html>
🔍 使用
<% %>
是 Vue CLI 内置的 html-webpack-plugin 的模板语法,支持环境判断。
✅ 验证是否成功
1. 开发环境测试
npm run serve
- 页面正常显示 Element UI 组件
- 浏览器网络面板中,没有加载 CDN 的 JS/CSS
2. 生产环境构建
npm run build
- 构建完成后,检查
dist/js/app.xxxx.js
文件大小:明显变小 - 打开
dist/index.html
,查看源码:包含 CDN 的<link>
和<script>
- 本地预览(如用
serve -s dist
):Element UI 组件正常工作
🔒 建议:生产环境使用固定版本号,避免升级导致兼容问题。
⚠️ 注意事项
项目 | 说明 |
---|---|
TypeScript | 如果使用 TS,需在 global.d.ts 中声明:declare const ELEMENT: any; |
SSR 项目 | 不适用此方案,CDN 无法在服务端加载 |
PWA | 如果使用 PWA,需确保 CDN 资源能被缓存或离线访问 |
安全性 | 内部系统建议私有化部署 Element UI 静态资源 |
🎯 总结
文件 | 配置内容 |
---|---|
vue.config.js | externals 生产环境排除 element-ui vue vuex vueRouter |
main.js | 正常全局导入 import Element UI |
index.html | 按环境引入 CDN 资源 |
这样就实现了 开发用本地,发布用 CDN 的最佳实践!