@meforma/vue-toaster 清除功能仅在拉入本地项目文件夹时有效,而不是从 node_modules
@meforma/vue-toaster clear function only works when pulled into local project folder, not from node_modules
如前所述,包 @meforma/vue-toaster
在 API here.
中有一个 clear()
函数
我的vue和vite项目设置:
main.js
import Toaster from '@meforma/vue-toaster'
app.use(Toaster, {
position: 'top',
useDefaultCss: false,
pauseOnHover: false
}).provide('toast', app.config.globalProperties.$toast)
Example.vue
<template>
<div class="view">
<div class="mt-10 flex gap-5">
<button class="btn btn-stealth" @click="showToast('default')">Default</button>
<button class="btn btn-primary" @click="showToast('primary')">Primary</button>
<button class="btn btn-success" @click="showToast('success')">Success</button>
<button class="btn btn-info" @click="showToast('info')">Info</button>
<button class="btn btn-warning" @click="showToast('warning')">Warning</button>
<button class="btn btn-danger" @click="showToast('error')">Error</button>
</div>
<div class="mt-10">
<button class="btn" @click="toast.clear">Clear Toasts</button>
<br><br>
<button class="btn" @click="clearToasts">Timeout Clear</button>
</div>
</div>
</template>
<script setup>
import { inject } from 'vue'
const toast = inject('toast')
// this works
function showToast (type) {
toast.show(`This is the ${type} type toast.`, {
type: type,
duration: false
})
}
// only works when vue-toaster is local in my projects src folder :S
function clearToasts () {
toast.clear()
}
</script>
package.json
{
"name": "test-project",
"version": "0.1.0",
"private": true,
"scripts": {
"dev": "vite --open",
"build": "vite build --out-dir dist",
"lint": "eslint src"
},
"dependencies": {
"@meforma/vue-toaster": "^1.3.0",
"@vitejs/plugin-vue": "^2.2.4",
"animate.css": "^4.1.1",
"axios": "^0.26.0",
"axios-auth-refresh": "^3.2.2",
"core-js": "^3.21.1",
"microtip": "^0.2.2",
"pinia": "^2.0.13",
"pinia-plugin-persistedstate": "^1.5.1",
"sass": "^1.49.9",
"vue": "^3.2.31",
"vue-meta": "^3.0.0-alpha.10",
"vue-router": "^4.0.13"
},
"devDependencies": {
"@tailwindcss/aspect-ratio": "^0.4.0",
"@tailwindcss/forms": "^0.5.0",
"@tailwindcss/line-clamp": "^0.3.1",
"@tailwindcss/typography": "^0.5.2",
"@vue/compiler-sfc": "^3.2.31",
"@vue/eslint-config-standard": "^6.1.0",
"autoprefixer": "^10.4.2",
"eslint": "^8.12.0",
"eslint-plugin-import": "^2.25.4",
"eslint-plugin-node": "^11.1.0",
"eslint-plugin-promise": "^6.0.0",
"eslint-plugin-standard": "^4.1.0",
"eslint-plugin-vue": "^8.6.0",
"postcss": "^8.4.7",
"tailwindcss": "^3.0.23",
"vite": "^2.8.6"
},
"eslintConfig": {
"root": true,
"env": {
"node": true
},
"extends": [
"plugin:vue/vue3-essential",
"@vue/standard"
],
"rules": {}
},
"browserslist": [
"> 1%",
"last 2 versions",
"not dead"
]
}
但是,当我将包拉入本地 src
文件夹并通过那里导入时,clear 工作得很好。除了移动代码所在的位置外,没有任何代码更改。
我完全不知道为什么会这样,如果有人见过类似的东西,将不胜感激。
我查看了 project github 的所有代码并在那里创建了一个问题。
我认为这可能与事件总线有关,但话又说回来,当从 node_modules
中拉出时它会起作用,所以为什么这让我头疼。
谢谢!
编辑 1:
更新了代码示例,您可以在本地 运行 遇到同样的问题:https://codesandbox.io/s/vue3-toaster-test-forked-m64htx?file=/src/components/HelloWorld.vue:854-868
特别是在 main.js
中,交换 vue-toaster
从中拉入的位置会导致清除功能 stop/start 工作。当 vue-toaster
位于我的项目 /src
中时清除工作正常,但从 node_modules
.
拉入时无法工作
编辑 2:
这是一个显示相同问题的 stackblitz(也使用 vite):https://stackblitz.com/edit/vitejs-vite-uqcdgd?file=src%2Fmain.js,src%2FApp.vue
原回答是误会。所以我根据问题的要点对其进行了编辑。
问题
- 从
node_modules
. 使用时,该软件包不起作用
- 当人们将它添加到项目中并直接使用它时,该包确实有效
原因
Vite只缓存包中的JS文件。我们可以在node_modules/.vite/deps/@meforma_vue-toaster.js
中看到
// The .vue file is point to original file
// node_modules/@meforma/vue-toaster/src/index.js
import Toaster2 from "/Users/admin/Work/test-projects/vite-demo-vue-plugin/node_modules/@meforma/vue-toaster/src/Toaster.vue";
// node_modules/@meforma/vue-toaster/src/api.js
import Toaster from "/Users/admin/Work/test-projects/vite-demo-vue-plugin/node_modules/@meforma/vue-toaster/src/Toaster.vue";
// The js file is cached here so Singleton pattern will breaks
// node_modules/@meforma/vue-toaster/src/helpers/event-bus.js
var Event = class {
constructor() {
this.queue = {};
}
...
}
event-bus.js 缓存在 .vite
文件夹中,但 Toaster.vue
文件不是。因此,当 Toaster.vue
使用 EventBus
时,它将调用 node_modules/@meforma/vue-toaster/
中的实例,而不是 .vite
缓存文件夹中的实例。并且打破了原包的单例模式
任何包含不可缓存文件和 JS 文件的包都可能发生此错误。
解决方法
这个bug只能从Vite端修复。所以在 Vite 修复它之前,我们需要从 Vite 缓存中排除包,正如 指出的那样:
// vite.config.js
export default defineConfig({
optimizeDeps: {
exclude: [
"@meforma/vue-toaster"
]
},
....
所以在 forking @meforma/vue-toaster, rewriting the Toaster in the composition API and changing the event bus to use mitt
, even went as far as to publish it to npmjs 之后,我可以复制所有内容,尽可能接近我最初使用包的方式....结果我的 re-written 包有完全相同的问题维特
进一步挖掘,我注意到在我的 /node_modules/
中有一个文件夹:/node_modules/.vite/deps/
,其中包含如下文件:@shanehoban_vue-toaster.js
... 所以我开始谷歌搜索,发现也许我应该从 Vite 优化中排除包...像这样:
vite.config.js
export default defineConfig({
optimizeDeps: {
exclude: [
"@meforma/vue-toaster"
]
},
....
现在,清除...正在发挥作用。
如前所述,包 @meforma/vue-toaster
在 API here.
clear()
函数
我的vue和vite项目设置:
main.js
import Toaster from '@meforma/vue-toaster'
app.use(Toaster, {
position: 'top',
useDefaultCss: false,
pauseOnHover: false
}).provide('toast', app.config.globalProperties.$toast)
Example.vue
<template>
<div class="view">
<div class="mt-10 flex gap-5">
<button class="btn btn-stealth" @click="showToast('default')">Default</button>
<button class="btn btn-primary" @click="showToast('primary')">Primary</button>
<button class="btn btn-success" @click="showToast('success')">Success</button>
<button class="btn btn-info" @click="showToast('info')">Info</button>
<button class="btn btn-warning" @click="showToast('warning')">Warning</button>
<button class="btn btn-danger" @click="showToast('error')">Error</button>
</div>
<div class="mt-10">
<button class="btn" @click="toast.clear">Clear Toasts</button>
<br><br>
<button class="btn" @click="clearToasts">Timeout Clear</button>
</div>
</div>
</template>
<script setup>
import { inject } from 'vue'
const toast = inject('toast')
// this works
function showToast (type) {
toast.show(`This is the ${type} type toast.`, {
type: type,
duration: false
})
}
// only works when vue-toaster is local in my projects src folder :S
function clearToasts () {
toast.clear()
}
</script>
package.json
{
"name": "test-project",
"version": "0.1.0",
"private": true,
"scripts": {
"dev": "vite --open",
"build": "vite build --out-dir dist",
"lint": "eslint src"
},
"dependencies": {
"@meforma/vue-toaster": "^1.3.0",
"@vitejs/plugin-vue": "^2.2.4",
"animate.css": "^4.1.1",
"axios": "^0.26.0",
"axios-auth-refresh": "^3.2.2",
"core-js": "^3.21.1",
"microtip": "^0.2.2",
"pinia": "^2.0.13",
"pinia-plugin-persistedstate": "^1.5.1",
"sass": "^1.49.9",
"vue": "^3.2.31",
"vue-meta": "^3.0.0-alpha.10",
"vue-router": "^4.0.13"
},
"devDependencies": {
"@tailwindcss/aspect-ratio": "^0.4.0",
"@tailwindcss/forms": "^0.5.0",
"@tailwindcss/line-clamp": "^0.3.1",
"@tailwindcss/typography": "^0.5.2",
"@vue/compiler-sfc": "^3.2.31",
"@vue/eslint-config-standard": "^6.1.0",
"autoprefixer": "^10.4.2",
"eslint": "^8.12.0",
"eslint-plugin-import": "^2.25.4",
"eslint-plugin-node": "^11.1.0",
"eslint-plugin-promise": "^6.0.0",
"eslint-plugin-standard": "^4.1.0",
"eslint-plugin-vue": "^8.6.0",
"postcss": "^8.4.7",
"tailwindcss": "^3.0.23",
"vite": "^2.8.6"
},
"eslintConfig": {
"root": true,
"env": {
"node": true
},
"extends": [
"plugin:vue/vue3-essential",
"@vue/standard"
],
"rules": {}
},
"browserslist": [
"> 1%",
"last 2 versions",
"not dead"
]
}
但是,当我将包拉入本地 src
文件夹并通过那里导入时,clear 工作得很好。除了移动代码所在的位置外,没有任何代码更改。
我完全不知道为什么会这样,如果有人见过类似的东西,将不胜感激。
我查看了 project github 的所有代码并在那里创建了一个问题。
我认为这可能与事件总线有关,但话又说回来,当从 node_modules
中拉出时它会起作用,所以为什么这让我头疼。
谢谢!
编辑 1:
更新了代码示例,您可以在本地 运行 遇到同样的问题:https://codesandbox.io/s/vue3-toaster-test-forked-m64htx?file=/src/components/HelloWorld.vue:854-868
特别是在 main.js
中,交换 vue-toaster
从中拉入的位置会导致清除功能 stop/start 工作。当 vue-toaster
位于我的项目 /src
中时清除工作正常,但从 node_modules
.
编辑 2:
这是一个显示相同问题的 stackblitz(也使用 vite):https://stackblitz.com/edit/vitejs-vite-uqcdgd?file=src%2Fmain.js,src%2FApp.vue
原回答是误会。所以我根据问题的要点对其进行了编辑。
问题
- 从
node_modules
. 使用时,该软件包不起作用
- 当人们将它添加到项目中并直接使用它时,该包确实有效
原因
Vite只缓存包中的JS文件。我们可以在node_modules/.vite/deps/@meforma_vue-toaster.js
// The .vue file is point to original file
// node_modules/@meforma/vue-toaster/src/index.js
import Toaster2 from "/Users/admin/Work/test-projects/vite-demo-vue-plugin/node_modules/@meforma/vue-toaster/src/Toaster.vue";
// node_modules/@meforma/vue-toaster/src/api.js
import Toaster from "/Users/admin/Work/test-projects/vite-demo-vue-plugin/node_modules/@meforma/vue-toaster/src/Toaster.vue";
// The js file is cached here so Singleton pattern will breaks
// node_modules/@meforma/vue-toaster/src/helpers/event-bus.js
var Event = class {
constructor() {
this.queue = {};
}
...
}
event-bus.js 缓存在 .vite
文件夹中,但 Toaster.vue
文件不是。因此,当 Toaster.vue
使用 EventBus
时,它将调用 node_modules/@meforma/vue-toaster/
中的实例,而不是 .vite
缓存文件夹中的实例。并且打破了原包的单例模式
任何包含不可缓存文件和 JS 文件的包都可能发生此错误。
解决方法
这个bug只能从Vite端修复。所以在 Vite 修复它之前,我们需要从 Vite 缓存中排除包,正如
// vite.config.js
export default defineConfig({
optimizeDeps: {
exclude: [
"@meforma/vue-toaster"
]
},
....
所以在 forking @meforma/vue-toaster, rewriting the Toaster in the composition API and changing the event bus to use mitt
, even went as far as to publish it to npmjs 之后,我可以复制所有内容,尽可能接近我最初使用包的方式....结果我的 re-written 包有完全相同的问题维特
进一步挖掘,我注意到在我的 /node_modules/
中有一个文件夹:/node_modules/.vite/deps/
,其中包含如下文件:@shanehoban_vue-toaster.js
... 所以我开始谷歌搜索,发现也许我应该从 Vite 优化中排除包...像这样:
vite.config.js
export default defineConfig({
optimizeDeps: {
exclude: [
"@meforma/vue-toaster"
]
},
....
现在,清除...正在发挥作用。