问题描述
我最近了解了延迟加载组件并开始使用它。现在,我正在尝试预取延迟加载的组件以及vue-router
路由。但是,使用chrome devtools时,我发现只有当我们实际导航到延迟加载的路由(在vue-router路由的情况下)或v-if
计算为true
并且组件被渲染(如果是延迟加载的组件)。
我还尝试在路由器以及组件import语句中使用webpackPrefetch: true
魔术字符串,但是这样做似乎没有什么区别。
项目结构:
主从布局
路由器配置:
import Vue from "vue";
import Router from "vue-router";
Vue.use(Router);
var routes = [
{
path: "/DetailPage",component: () => import(/* webpackChunkName: "Detail-chunk" */ "AppModules/views/MyModuleName/DetailPage.vue")
},{
path: "/MasterPage",component: () => import("AppModules/views/MyModuleName/MasterPage.vue")
}
]
export const router = new Router({
routes: routes,stringifyQuery(query) {
// encrypt query string here
}
});
export default router;
主视图:
<template>
<div @click="navigate">
Some text
</div>
</template>
<script>
export default {
name: "MasterPage",methods: {
navigate() {
this.$router.push({
path: "/DetailPage",query: {},});
},},};
</script>
详细信息页面:
<template>
<div>
<my-component v-if="showComponent" />
<div @click="showComponent = true">Show Component</div>
</div>
</template>
<script>
const MyComponent = () => import(/* webpackChunkName: "MyComponent-chunk" */ "AppCore/components/AppElements/Helpers/MyComponent");
export default {
name: "DetailPage",components: {
MyComponent,data() {
return {
showComponent: false
}
}
};
</script>
vue.js.config文件:
const path = require("path");
const BundleAnalyzerPlugin = require("webpack-bundle-analyzer")
.BundleAnalyzerPlugin;
module.exports = {
publicPath: "some-url",outputDir: "./some/path",chainWebpack: webapckConfig => {
webapckConfig.plugin("html").tap(() => {
return [
{
inject: true,filename: "index.html",template: "./public/index.html"
}
];
});
},productionSourceMap: true,configureWebpack: {
plugins: [
new BundleAnalyzerPlugin({
analyzerMode: "server",generateStatsFile: false,statsOptions: {
excludeModules: "node_modules"
}
})
],output: {
filename: "some file name",libraryTarget: "window"
},module: {
rules: [
{
test: /\.(woff|woff2)(\?v=\d+\.\d+\.\d+)?$/,use: [
{
loader: "url-loader",options: {
limit: 50000,fallback: "file-loader",outputPath: "/assets/fonts",name: "[name].[ext]?hash=[hash]"
}
}
]
}
]
},resolve: {
alias: {
vue$: process.env.NODE_ENV == 'production' ? 'vue/dist/vue.min.js' : 'vue/dist/vue.js',AppCore: path.resolve(__dirname,"..","AppCoreLite"),AppModules: path.resolve(__dirname,"AppModulesLite")
}
}
}
};
异步路由和组件均会分成单独的块,但这些块不会被预取。
导航到主视图时,在“网络”标签中看不到Detail-chunk.[hash].js
。仅在执行母版页中的navigate
方法时才会请求它(这是没有预取的正确的延迟加载行为)。
现在,当我进入详细信息页面时,仅在MyComponent-chunk.[hash].js
变为showComponent
(单击按钮时)时才请求true
我还在一些地方读到vue-cli
v3确实默认启用了预取功能,并且不需要webpack魔术字符串。我还尝试通过删除webpackPrefetch
注释来做到这一点,但这没什么区别。
我做了vue-cli-service inspect
,发现webpack配置中确实存在预取插件:
/* config.plugin('preload') */
new PreloadPlugin(
{
rel: 'preload',include: 'initial',fileBlacklist: [
/\.map$/,/hot-update\.js$/
]
}
),/* config.plugin('prefetch') */
new PreloadPlugin(
{
rel: 'prefetch',include: 'asyncChunks'
}
),
更新:我尝试使用config.plugins.delete('prefetch');
删除预取webpack插件,然后使用webpack魔术注释:/* webpackPrefetch: true */
,但这没什么区别。
如何实现预取功能?
解决方法
延迟加载的组件仅在用户单击路由时才加载。如果您想在组件之前加载它,那就不要使用延迟加载。
vue-router
会将组件加载到内存,并动态交换标签的内容,即使您将使用正常加载的组件也是如此。
您需要根据需要实施vue-router-prefetch软件包。这是工作中的demo。
注意:在工作的演示中,您可以从x = minX;
y = minY;
w = maxX-minX;
h = maxY-minY;
letterBounds.add(new Rectangle(x,y,w,h));
中注意到,从console.log
导入的page 2
组件仅预提取了QuickLink
代码:
vue-router-prefetch
,
我通过创建一个在自定义时间后加载的简单预取组件解决了这个问题。
Prefetch.vue
<script>
import LazyComp1 from "./LazyComp1.vue";
import LazyComp2 from "./LazyComp2.vue";
export default {
components:{
LazyComp1,LazyComp2,}
}
</script>
App.vue
<template>
<Prefech v-if="loadPrefetch"></Prefech>
</template>
<script>
export default {
components: {
Prefech: () => import("./Prefetch");
},data() {
return {
loadPrefetch: false
}
},mounted() {
setTimeout(() => {
this.loadPrefetch = true;
},1000);
}
}
</script>
,
我正在开发移动应用。并希望在显示启动画面时动态加载一些组件。
@Thomas 的回答是一个很好的解决方案(一个 Prefetch 组件),但是它不会在 shadow dom 中加载该组件,并且不会通过 Vetur 验证(每个组件都必须有自己的模板)
这是我的代码:
main.vue
<template>
<loader />
</template>
<script>
import Loader from './Loader'
const Prefetch = () => import('./Prefetch')
export default {
name: 'Main',components: {
Loader,Prefetch
}
}
</script>
Prevetch.vue
<template>
<div id="prefetch">
<lazy-comp-a />
<lazy-comp-b />
</div>
</template>
<script>
import Vue from 'vue'
import LazyCompA from './LazyCompA'
import LazyCompB from './LazyCompB'
Vue.use(LazyCompA)
Vue.use(LazyCompB)
export default {
components: {
LazyCompA,LazyCompB
}
}
</script>
<style lang="scss" scoped>
#prefetch {
display: none !important;
}
</style>
加载器组件被加载和渲染,然后预取组件可以动态加载任何东西。