vue-cli 通过extends引入 CDN外部资源

本文介绍如何通过配置Vue项目的webpack,利用externals加载外部CDN资源,减少打包体积。通过在vue.config.js中设置chainWebpack和externals,指定不打包第三方依赖,并在index.html中引入CDN资源。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

使用 vuewebpack 模版开发项目时,使用 npm install安装的各种组件和依赖到本地
默认情况下 通过import语法导入的第三方依赖包 最终会被打包合并到同一个文件中
从而导致打包成功后 单文件体积过大的问题
为了解决问题 可以通过webpackexternals节点 配置并加载外部的CDN资源
凡是声明在externals中的第三方依赖包 都不会被打包

未配置前打包的大小 最下面有配置完之后再次打包的大小
在这里插入图片描述
通过vue-cli 3.0 生成的项目 默认是隐藏了所有的webpack配置项
如果有修改webpack默认配置的需求 可以在项目根目录下 按需创建vue.config.js文件
从而对项目打包发布过程做自定义配置
项目根目录新建 vue.config.js
这里加了chainWebpack 自定义打包入口
chainWebpack步骤
src的文件目录下新建 main-prod.jsmain-dev.js把原本main.js的所有内容复制到新建的js
目前两个文件里面的内容一模一样 删掉原本的main.js

vue.config.js加入以下chainWebpack的配置

module.exports = {
    chainWebpack: config => {
        // 发布模式
        config.when(process.env.NODE_ENV === 'production', config => {
            config.entry('app').clear().add('./src/main-prod.js')
        })
        // 开发模式
        config.when(process.env.NODE_ENV === 'development', config => {
            config.entry('app').clear().add('./src/main-dev.js')
        })
    }
}

然后再把 externals 的配置加上 这里加的是项目中所使用引入的包

config.set('externals', {
     vue: 'Vue',
     'vue-router': 'VueRouter',
     axios: 'axios',
     lodash: '_',
     echarts: 'echarts',
     nprogress: 'NProgress',
     'vue-quill-editor': 'VueQuillEditor'
 })

加完如下
在这里插入图片描述
然后在main-prod.js 文件中删除 引入的包的css文件
根据项目不同 这里删除和引用的文件也是不一样的
在这里插入图片描述
然后在需要在public/index.html文件的头部 添加CDN资源引用
添加的引用就是在 config.set 中的文件
在这里插入图片描述
最后在 vue ui 面板运行build任务 打包成功 文件大小就小了很多
在这里插入图片描述

<think>好的,我现在需要回答用户关于Vue3是否可以通过Web Components动态使用单文件组件(SFC)的问题,以及如果不行的话,如何在不使用工程化工具的情况下实现即写即用。首先,我得先理清楚这两个技术的关系和限制。 首先,Vue3确实支持将组件封装为Web Components,这可以通过Vue的defineCustomElement方法实现。用户提到的是动态使用单文件组件,这里可能需要明确动态的含义。如果是想在运行时动态加载.vue文件并注册为Web Components,这可能会有问题,因为浏览器本身不支持直接解析.vue单文件组件。通常,SFC需要被构建工具(如Vite或Vue CLI)编译成JavaScript模块,才能在浏览器中运行。 接下来,用户希望不通过工程化的方式,也就是说不使用打包工具,直接写代码即用。这时候需要考虑如何在不构建的情况下使用Vue3和Web Components。可能的思路是使用Vue的运行时版本,直接在HTML引入Vue,然后编写组件并转换为自定义元素。 不过,单文件组件通常需要编译,尤其是处理<template>块和CSS作用域。如果没有构建步骤,直接在浏览器中解析.vue文件是不现实的。因此,可能需要放弃SFC,改用纯JavaScript定义组件,或者寻找其他方式在运行时处理.vue文件,比如使用浏览器端的编译器,但这可能会影响性能,并且不太常见。 然后,我需要验证Vue3的defineCustomElement是否支持动态注册。根据文档,defineCustomElement可以将Vue组件转换为自定义元素,但组件需要在代码中预先定义,或者在运行时动态导入已编译的组件。如果用户想动态加载外部的.vue文件,可能需要额外的机制来编译这些文件,比如使用浏览器中的TypeScript编译器或者其他在线工具,但这样复杂且不推荐。 可能的解决方案包括: 1. 避免使用SFC,改用纯JavaScript对象定义组件,然后使用defineCustomElement转换为Web Component。 2. 如果必须使用SFC,需要一个简单的构建步骤来预先编译组件,即使不使用完整的工程化工具,可能需要单个文件的编译。 3. 利用动态导入和模块加载,但依然需要组件已经被编译为ES模块。 需要检查是否有办法在浏览器中直接运行.vue文件,比如使用Vue的ES模块构建,或者某些CDN服务可以实时编译。例如,可以使用Skypack或esm.sh来导入Vue,然后通过import语句加载组件,但可能还是需要组件已经被编译。 总结,Vue3通过Web Components动态使用SFC在没有构建步骤的情况下不可行,因为浏览器无法解析SFC。替代方案是使用非SFC的组件定义,或者使用轻量级工具进行即时编译,如单个文件的编译命令,或者在线编辑器如CodePen、JSFiddle等,但这些可能属于工程化的范畴。因此,最终的解决方案可能需要在纯浏览器环境中避免SFC,改用JavaScript对象定义组件,并结合defineCustomElement来创建Web Components。</think>Vue3可以通过Web Components技术动态使用单文件组件,但需要特殊处理且存在限制。以下是具体实现方案: $$ \textcolor{blue}{实现步骤} \\ 1.\ 使用\ Vue3\ 的\ defineCustomElement\ 方法 \\ 2.\ 放弃\ .vue\ 文件扩展名 \\ 3.\ 采用\ JavaScript\ 对象形式定义组件 \\ 4.\ 通过\ <script type="module">\ 实现模块化 $$ **具体实现代码示例**: ```html <!DOCTYPE html> <html> <head> <!-- 直接引入Vue3的ES模块版本 --> <script type="module"> import { defineCustomElement } from 'https://unpkg.com/vue@3/dist/vue.esm-browser.js' // 定义Vue组件(替代SFC) const MyComponent = { template: ` <div :style="{ color: props.textColor}"> {{ greeting }},动态内容:{{ dynamicContent }} <slot></slot> </div> `, props: ['textColor', 'dynamicContent'], setup(props) { return { greeting: '你好,世界!', props } } } // 转换为Web Component customElements.define('my-component', defineCustomElement(MyComponent) ) </script> </head> <body> <!-- 动态使用组件 --> <my-component text-color="blue" dynamic-content="实时数据" > <p>通过插槽插入的内容</p> </my-component> </body> </html> ``` $$ \textcolor{red}{关键限制说明} \\ 1.\ \text{无法直接使用.vue单文件组件} \\ 2.\ \text{需手动处理样式隔离(可添加shadowRoot)} \\ 3.\ \text{需自行实现响应式更新优化} $$ **进阶方案**(添加样式隔离): ```javascript const MyComponent = { styles: [ `:host { display: block; } p { color: var(--primary-color, red); }` ], template: `<p>带样式的组件</p>`, setup() { // 业务逻辑... } } // 转换时自动处理样式 const CustomElement = defineCustomElement(MyComponent) customElements.define('styled-component', class extends CustomElement { constructor() { super() this.attachShadow({ mode: 'open' }) this.shadowRoot.adoptedStyleSheets = [ new CSSStyleSheet().replaceSync( MyComponent.styles.join('') ) ] } }) ``` **动态加载方案**: ```javascript // 动态加载组件 async function loadComponent(url) { const module = await import(url) customElements.define(module.tagName, defineCustomElement(module.component) ) } // 使用示例 loadComponent('./components/dynamic-component.js') ``` $$ \textcolor{green}{最佳实践建议} \\ 1.\ 简单组件直接使用对象形式 \\ 2.\ 复杂组件可预先用vite单文件编译 \\ 3.\ 使用\ Constructable Stylesheets\ 管理样式 \\ 4.\ 通过\ MutationObserver\ 实现动态属性响应 $$ 这种方案的优势在于: - 无需webpack/vite等构建工具 - 支持现代浏览器的原生模块加载 - 组件可跨框架使用 - 实时更新效果可见 对于需要复杂功能的场景,建议结合Vite的即时编译功能,通过`npm init vite@latest`创建最小化工程,使用`<script type="module">`直接引用编译后的ES模块文件。
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值