vue.js - 将插件与 Rollup 捆绑在一起,但在客户端应用程序的包 (Nuxt) 中导入了重复的 Vue.js 包
问题描述
亲爱的 Stack Overflow / Vue.js / Rollup 社区
对于使用 Vue 和 Rollup 的主要插件开发人员来说,这可能是一个菜鸟问题。我会非常明确地写下这个问题,希望它可以在未来帮助像我这样的其他菜鸟。
我有一个简单的插件,可以帮助进行表单验证。这个插件中的一个组件导入了 Vue,以便以编程方式创建一个组件并在挂载时附加到 DOM,如下所示:
import Vue from 'vue'
import Notification from './Notification.vue' /* a very simple Vue component */
...
mounted() {
const NotificationClass = Vue.extend(Notification)
const notificationInstance = new NotificationClass({ propsData: { name: 'ABC' } })
notificationInstance.$mount('#something')
}
这可以按预期工作,并且此插件使用 Rollup 捆绑,配置如下:
import vue from 'rollup-plugin-vue'
import babel from 'rollup-plugin-babel'
import { terser } from 'rollup-plugin-terser'
import resolve from 'rollup-plugin-node-resolve'
import commonjs from 'rollup-plugin-commonjs'
export default {
input: 'src/index.js',
output: {
name: 'forms',
globals: {
vue: 'Vue'
}
},
plugins: [
vue(),
babel(),
resolve(),
commonjs(),
terser()
],
external: ['vue']
}
正如你所看到的,Vue.js 在这个包中被外部化了。目的(和假设)是导入此插件的客户端应用程序将在 Vue 上运行,因此无需在此处捆绑它(假设)。
捆绑器使用的非常简单的 src/index.js 如下:
import Form from './Form.vue'
export default {
install(Vue, _) {
Vue.component('bs-form', Form)
}
}
Rollup 创建 2 个文件(一个 esm 和一个 umd)并在 plugins package.json 文件中引用它们,如下所示:
"name": "bs-forms",
"main": "./dist/umd.js",
"module": "./dist/esm.js",
"files": [
"dist/*"
],
"scripts": {
"build": "npm run build:umd & npm run build:es",
"build:es": "rollup --config rollup.config.js --format es --file dist/esm.js",
"build:umd": "rollup --config rollup.config.js --format umd --file dist/umd.js"
}
到目前为止,一切都按预期工作,并且捆绑包生成得很好。
客户端应用程序(Nuxt SSR)通过一个非常简单的插件文件导入来导入这个插件(使用 npm-link,因为它正在开发中):
/* main.js*/
import Vue from 'vue'
import bsForms from 'bs-forms'
Vue.use(bsForms)
此插件文件 (main.js) 作为插件添加到 nuxt.config.js:
// Nuxt Plugins
...
plugins: [{src: '~/plugins/main'}]
...
一切仍然按预期工作,但问题来了:
由于客户端是 Nuxt 应用程序,因此默认情况下会导入 Vue,但也会在客户端中导入外部化的 Vue 模块(通过表单插件)。因此,客户端捆绑包中存在此包的副本。
我猜客户端应用程序可以配置其 webpack 配置以删除这个重复的模块。也许通过使用诸如 Dedupe 插件之类的东西?有人可以建议如何最好地处理这样的情况吗?
但我真正想学习的是,首先捆绑插件的最佳实践,这样客户端就不必更改其配置中的任何内容,只需导入此插件并继续前进。
我知道在插件中导入 Vue.js 一开始可能不是一件好事。但是像这样的导入也可能有其他原因,例如想象插件可以用 Typescript 和 Vue.js 编写/Typescript 是使用 Vue.extend 语句(见下文)编写的,它也导入 Vue(按顺序启用类型接口):
import Vue from 'vue'
const Component = Vue.extend({
// type inference enabled
})
所以这是一个很长的问题。请汇总的大师们,通过建议最佳实践方法(或您的方法)来帮助我和社区来处理此类情况。
谢谢!!!!
解决方案
我遇到了同样的问题,我发现@vatson 的这个答案非常有帮助
您的问题是“npm 链接”、nodejs 模块加载的性质以及 vue 对来自不同地方的多个实例的不容忍性的组合。
简短介绍 nodejs 中的导入如何工作。如果您的脚本有某种库导入,那么 nodejs 最初会在本地 node_modules 文件夹中查找,如果本地 node_modules 不包含所需的依赖项,那么 nodejs 会转到上面的文件夹以查找 node_modules 和您在那里导入的依赖项。
你不需要在 NPM 上发布你的包。如果您使用本地生成包npm pack
然后将其安装在您的其他项目中就足够了npm install /absolute_path_to_your_local_package/your_package_name.tgz
。如果您更新包中的某些内容,您可以在其他项目中重新安装它,一切都应该正常。
npm pack
这是关于和npm link
https://stackoverflow.com/a/50689049/6072503之间区别的来源。
推荐阅读
- reactjs - 为什么我不断收到 500(内部服务器错误)GET http://localhost:3000/favicon.ico 500(内部服务器错误)?
- core-data - 在 SwiftUI 中显示来自 CoreData 的图像
- mysql - MySQL SELECT 计数与 ORDER BY
- javascript - JavaScript 使用 classList 属性调用内部变量
- python - 使用 matplotlib 的屏幕词云上没有输出
- php - 切换器 php。我的问题是切换器。当我切换和表单应该动态更改
- r - 使用 ggplot 曲线 geom_line()
- php - 如何在PHP中双重分割字符串?
- javascript - Javascript 参数处理
- python - 在 CSV 数据框中查找列时 Streamlit Panda 查询函数语法错误