我怎样才能正确地在 Vue.js 中延迟加载 json 文件以减少包大小?
How can I correctly lazy load a json file in Vue.js to reduce bundle size?
我正在为我的项目使用 Vue.js 和 Laravel,并且最近使用名为 Lottie 的插件添加了两个动画。每个动画都是一个组件,它们都使用一个单独的 JSON 文件来为一组 PNG 图像(类似于 PNG 序列)设置动画。这两个JSON文件本地保存在项目文件夹下路径/public/data/.
首先,除非我输入绝对路径 (/users/username/documents/projectname/public/data/filename.json[,否则不会读取 JSON 文件=53=]), 有没有办法仅通过使用 /data/filename.json?
就可以让它工作
其次,当我在我的组件中添加以下代码时,我的 JS 文件被编译为预期的单独块:
const animationData = () =>
import("/users/username/documents/projectname/public/data/filename.json");
当动画尝试 运行:
时出现以下错误
Invalid prop: type check failed for prop "data". Expected Object, got Function
found in
---> <VueLottie>
然而,当我在我的组件中使用正常导入导入我的 json 文件时,如下所示,它工作正常并显示动画:
import animationData from "/users/username/documents/projectname/public/data/filename.json";
我的动画组件都是这样设置的:
<template>
<vue-lottie ref="lottie" loop autoplay :data="animationData" :height="400" :width="400"></vue-lottie>
</template>
<script>
import vueLottie from "vue-lottie-ssr";
import animationData from '/users/username/documents/projectname/public/data/filename.json'
export default {
name: 'animation',
components: {
vueLottie
},
data () {
return {
speed: 1,
animationData
}
},
computed: {
lottie () {
return this.$refs.lottie
}
}
}
</script>
我也尝试过在组件挂载时通过axios调用获取JSON文件,但出现同样的错误。
更新
我更新了我的代码,以便延迟加载每个组件而不是 JSON 文件。像这样:
components: {
WinAnimation: () => import("./WinAnimation.vue");
LoseAnimation: () => import("./LoseAnimation.vue");
}
但是现在我收到以下错误:
Unknown custom element: <win-animation> - did you register the component correctly? For recursive components, make sure to provide the "name" option.
更新 2
我明白了为什么我会收到一条错误消息。正确的方法是在父 vue 文件中的脚本顶部添加以下内容。
const winAnimation = () => import("./WinAnimation.vue");
const loseAnimation = () => import("./LoseAnimation.vue");
然后在 export default {...} 里面我忘了添加名字,所以:
components: { winAnimation, loseAnimation }
现在我的代码已经拆分,我的 app.js 文件大小减少了将近一半! :)
当设置 animationData
属性 时,它是一个函数,因此行:
Expected Object, got Function
它需要一个对象,而不是一个函数。
函数是:
const animationData = () =>
import("/users/username/documents/projectname/public/data/filename.json");
当定义 animationData
属性 时,您需要设置一个对象作为它的值。然后在挂载 fetch
数据时(如果你愿意,也可以使用 Axios)更新组件上的 animationData
属性。
N.B.我没用过Vue,所以希望我说的是对的。
export default {
name: 'animation',
components: {
vueLottie
},
data () {
return {
speed: 1,
animationData: {}
}
},
computed: {
lottie () {
return this.$refs.lottie
}
},
mounted() {
fetch('/users/username/documents/projectname/public/data/filename.json')
.then(response => response.json())
.then(json => this.animationData = json;);
)
}
}
1st - 不要使用 vue-lottie library. If you take a look at the source code, the main and only thing which should be provided by this library is component src/lottie.vue
(+ it's dependency lottie-web) 但出于某种原因,NPM 包还包含整个演示应用程序 包括 演示 JSON 文件(src/assets/pinjump.json
)
如果您看一下 lottie.vue
组件,它只是 lottie-web
的非常小且非常简单的包装器,它提供了主要功能。通过摆脱 vue-lottie
,您将获得以下好处:
vue-lottie
完全忽略了使用 path
instead of animationData
的 lottie-web
选项之一——这里的文档不是很清楚,但我猜想通过提供 path
,该库将尝试临时下载动画数据,因此您无需将其包含在您的包中。值得一试恕我直言...
正在按需加载动画数据
- 为什么要在 JSON 文件上使用动态导入而不是动态导入整个组件?通过在组件级别创建单独的块,动态块将不仅包括您的 json 数据,还包括同样不小的
lottie-web
数据。 Vue 将处理组件的加载而无需任何额外的代码更改...
- 如果您仍然只想按需加载 JSON 数据,您必须了解 Webpack 动态导入 (
import(".....")
) 正在返回 Promise 和 lottie-web
(然后 vue-lottie
) 期待对象。所以你必须这样做:
<script>
import lottie from 'lottie-web';
const animationData = () =>
import("/users/username/documents/projectname/public/data/filename.json");
export default {
mounted () {
animationData().then(function(data) {
this.anim = lottie.loadAnimation({
// other options
animationData: data
})
});
}
}
</script>
更新
在考虑将第 3 方组件添加到项目中时,您应该始终非常小心。我注意到的另一件事是 lottie-web
有 destroy()
method in it's API. This indicates that it is creating some resources (DOM elements probably) which needs to be cleaned up. This is something vue-lottie
component is not handling at all and can lead to nasty memory leaks in your app. You can read about the problem here
我正在为我的项目使用 Vue.js 和 Laravel,并且最近使用名为 Lottie 的插件添加了两个动画。每个动画都是一个组件,它们都使用一个单独的 JSON 文件来为一组 PNG 图像(类似于 PNG 序列)设置动画。这两个JSON文件本地保存在项目文件夹下路径/public/data/.
首先,除非我输入绝对路径 (/users/username/documents/projectname/public/data/filename.json[,否则不会读取 JSON 文件=53=]), 有没有办法仅通过使用 /data/filename.json?
就可以让它工作其次,当我在我的组件中添加以下代码时,我的 JS 文件被编译为预期的单独块:
const animationData = () =>
import("/users/username/documents/projectname/public/data/filename.json");
当动画尝试 运行:
时出现以下错误Invalid prop: type check failed for prop "data". Expected Object, got Function
found in
---> <VueLottie>
然而,当我在我的组件中使用正常导入导入我的 json 文件时,如下所示,它工作正常并显示动画:
import animationData from "/users/username/documents/projectname/public/data/filename.json";
我的动画组件都是这样设置的:
<template>
<vue-lottie ref="lottie" loop autoplay :data="animationData" :height="400" :width="400"></vue-lottie>
</template>
<script>
import vueLottie from "vue-lottie-ssr";
import animationData from '/users/username/documents/projectname/public/data/filename.json'
export default {
name: 'animation',
components: {
vueLottie
},
data () {
return {
speed: 1,
animationData
}
},
computed: {
lottie () {
return this.$refs.lottie
}
}
}
</script>
我也尝试过在组件挂载时通过axios调用获取JSON文件,但出现同样的错误。
更新
我更新了我的代码,以便延迟加载每个组件而不是 JSON 文件。像这样:
components: {
WinAnimation: () => import("./WinAnimation.vue");
LoseAnimation: () => import("./LoseAnimation.vue");
}
但是现在我收到以下错误:
Unknown custom element: <win-animation> - did you register the component correctly? For recursive components, make sure to provide the "name" option.
更新 2
我明白了为什么我会收到一条错误消息。正确的方法是在父 vue 文件中的脚本顶部添加以下内容。
const winAnimation = () => import("./WinAnimation.vue");
const loseAnimation = () => import("./LoseAnimation.vue");
然后在 export default {...} 里面我忘了添加名字,所以:
components: { winAnimation, loseAnimation }
现在我的代码已经拆分,我的 app.js 文件大小减少了将近一半! :)
当设置 animationData
属性 时,它是一个函数,因此行:
Expected Object, got Function
它需要一个对象,而不是一个函数。
函数是:
const animationData = () =>
import("/users/username/documents/projectname/public/data/filename.json");
当定义 animationData
属性 时,您需要设置一个对象作为它的值。然后在挂载 fetch
数据时(如果你愿意,也可以使用 Axios)更新组件上的 animationData
属性。
N.B.我没用过Vue,所以希望我说的是对的。
export default {
name: 'animation',
components: {
vueLottie
},
data () {
return {
speed: 1,
animationData: {}
}
},
computed: {
lottie () {
return this.$refs.lottie
}
},
mounted() {
fetch('/users/username/documents/projectname/public/data/filename.json')
.then(response => response.json())
.then(json => this.animationData = json;);
)
}
}
1st - 不要使用 vue-lottie library. If you take a look at the source code, the main and only thing which should be provided by this library is component src/lottie.vue
(+ it's dependency lottie-web) 但出于某种原因,NPM 包还包含整个演示应用程序 包括 演示 JSON 文件(src/assets/pinjump.json
)
如果您看一下 lottie.vue
组件,它只是 lottie-web
的非常小且非常简单的包装器,它提供了主要功能。通过摆脱 vue-lottie
,您将获得以下好处:
vue-lottie
完全忽略了使用path
instead ofanimationData
的lottie-web
选项之一——这里的文档不是很清楚,但我猜想通过提供path
,该库将尝试临时下载动画数据,因此您无需将其包含在您的包中。值得一试恕我直言...正在按需加载动画数据
- 为什么要在 JSON 文件上使用动态导入而不是动态导入整个组件?通过在组件级别创建单独的块,动态块将不仅包括您的 json 数据,还包括同样不小的
lottie-web
数据。 Vue 将处理组件的加载而无需任何额外的代码更改... - 如果您仍然只想按需加载 JSON 数据,您必须了解 Webpack 动态导入 (
import(".....")
) 正在返回 Promise 和lottie-web
(然后vue-lottie
) 期待对象。所以你必须这样做:
- 为什么要在 JSON 文件上使用动态导入而不是动态导入整个组件?通过在组件级别创建单独的块,动态块将不仅包括您的 json 数据,还包括同样不小的
<script>
import lottie from 'lottie-web';
const animationData = () =>
import("/users/username/documents/projectname/public/data/filename.json");
export default {
mounted () {
animationData().then(function(data) {
this.anim = lottie.loadAnimation({
// other options
animationData: data
})
});
}
}
</script>
更新
在考虑将第 3 方组件添加到项目中时,您应该始终非常小心。我注意到的另一件事是 lottie-web
有 destroy()
method in it's API. This indicates that it is creating some resources (DOM elements probably) which needs to be cleaned up. This is something vue-lottie
component is not handling at all and can lead to nasty memory leaks in your app. You can read about the problem here