延迟加载的vue-router组件不适用于SSR

时间:2019-10-03 10:15:03

标签: javascript vue.js webpack vue-router laravel-mix

对于server.js和client.js,我有两个不同的入口点。(我使用的是vue-server-renderer和laravel-mix)-(我的server.js和client.js看起来与此处所述完全相同-{ {3}},如果我进行静态导出import Test from '../views/Test',则可以使用。

如果我尝试在不延迟加载的情况下导入路由,则SSR可以工作:

import Test from "../views/Test";

export const routes = [{
    path: '/my-route',
    name: "Test",  
    component: Test,
}]

但是,如果我尝试延迟加载,则会在SSR上失败:

export const routes = [{
    path: '/my-route',
    name: "Test"
    component: () => import('../views/Test.vue'),
}]
  

找不到模块'./js/chunks/server/0.js?id=c3384f174123f0848451'

对于() => import('../views/Home.vue),client.js有效,只有server.js不起作用。


我的server.js

import renderVueComponentToString from 'vue-server-renderer/basic';
import app from './app';
import {router} from './router/index';

new Promise((resolve, reject) => {
    router.push(context.url);
    router.onReady(() => {
        resolve(app);
    }, reject);
})
    .then(app => {
        renderVueComponentToString(app, (err, res) => {
            if (err) throw new Error(err);

            dispatch(res);
        });
    });

完整错误是:

  

命令“ / usr / bin / node /home/vagrant/Code/project/storage/app/ssr/1228cfee3f79dc5949bd898950384e53.js”失败退出代码:1(常规错误)

     

工作目录:/ home / vagrant / Code / project / public输出:

     

================错误输出:================ Internal / modules / cjs / loader.js:628 throw呃; ^

     

错误:找不到模块'./js/chunks/server/0.js?id=c3384f174123f0848451'


更新

我想我可能知道为什么会这样(我可能错了):

export const routes = [{
     path: '/', 
     name: "Home", 
     component: () => import('../views/Home')
}]

使用此代码,我得到一个错误:

  

错误:找不到模块'./js/chunks/server/0.js?id=c3384f174123f0848451'

     

命令“ / usr / bin / node /home/vagrant/Code/project/storage/app/ssr/717358e60bfd52035a1e58256cdfbba0.js”失败。退出代码:1(一般错误)工作目录:/ home / vagrant / Code / project / public输出:===============错误输出:======== ======== Internal / modules / cjs / loader.js:628 throw err; ^错误:找不到模块'./js/chunks/server/0.js?id=c3384f174123f0848451'

查看路径: 在我的编译文件(位于public/js中)中,有以下一行:

var chunk = require("./js/chunks/server/" + ({}[chunkId]||chunkId) + ".js?id=" + {"0":"c3384f174123f0848451"}[chunkId] + "");

这似乎是一条相对路径。但是,该文件实际上是按照我在config/ssr.php-'temp_path' => storage_path('app/ssr')中指定的格式运行的,因此找不到该路径。

但是,即使我将temp_path更改为public_path(),以便它可以从./js/chunks/server/(即public/js/chunks/server/0.js)中找到块,它仍然会引发相同的错误。即使SSR的temp_path是不同的。

  

命令“ / usr / bin / node /home/vagrant/Code/project/public/3560d8d101faa4bdef316054b14873cc.js”失败。退出代码:1(一般错误)工作目录:/ home / vagrant / Code / project / public输出:===============错误输出:======== ======== Internal / modules / cjs / loader.js:628 throw err; ^错误:找不到模块'./js/chunks/server/0.js?id=c3384f174123f0848451'

如果我在console.log(_dirname)renderVueComponentToString(),它也会返回我'/'

2 个答案:

答案 0 :(得分:1)

我解决了它,现在它可以在客户端使用SSR和代码拆分功能-如果您有更好的主意,我仍然不屑一顾。

我使用了spatie/laravel-server-side-rendering,它很容易设置。

这是我的解决方案(以及我对spatie / laravel-server-side-rendering所做的更改):

我了解了如何从charlesBochet's comment中分离捆绑包,但是我没有使用2个webpack.mix.js文件。

  • package.json
"scripts": {
    // concurrently is just for building them asynchronously 
    "dev-all": "concurrently \"npm --section=server run dev\" \"npm --section=client run dev\"  --kill-others-on-fail",

    // can also build them separately if you wish
    "dev-client": "npm --section=client run dev",
    "dev-server": "npm --section=server run dev"
     ...
}
  • webpack.mix.js
if (process.env.npm_config_section === 'server') {
    mix.js('resources/js/app-server.js', 'public/js')
        .webpackConfig({
            target: 'node',

            // Prevent code-splitting for server-build
            plugins: [
                new webpack.optimize.LimitChunkCountPlugin({
                    maxChunks: 1,
                })
            ],
        })
        // merge manifest is a package for merging manifests,
        // otherwise they'll get overwritten by each other
        // https://github.com/kabbouchi/laravel-mix-merge-manifest
        .mergeManifest()
        .version();

} else if (process.env.npm_config_section === 'client') {
    mix.js('resources/js/app-client.js', 'public/js')
        .webpackConfig({
            target: 'web',
            output: {
                chunkFilename: 'js/chunks/[name].js?id=[chunkhash]',
                publicPath: '/',
            },
        })
        .mergeManifest()
        .version();

    // Only build css with the client build, server build only needs
    // the html and not the css
    mix.sass('resources/sass/app.scss', 'public/css')
} else {
    console.log(
        '\x1b[41m%s\x1b[0m',
        'Provide correct --section argument to build command: server, client'
    );
    throw new Error('Provide correct --section argument to build command!')
}
  • app-server.js-应等待路由器准备就绪
new Promise((resolve, reject) => {
    router.push(context.url);
    router.onReady(() => {
        resolve(app);
    }, reject);
})
    .then(app => {
        renderVueComponentToString(app, (err, res) => {
            if (err) throw new Error(err);
            dispatch(res);
        });
    });
  • app-client.js
router.onReady(function() {
    app.$mount('#app');
})
  • 最后,路由器文件代码拆分功能适用于app-client.js
export const routes = [
{
    path: '/',
    name: "Home",
    component: () => import('../views/Home.vue')
},

答案 1 :(得分:0)

不确定问题的出处,但您应该阅读以下内容:

  

请注意,在返回/安装应用程序之前,仍然有必要在服务器和客户端上同时使用 router.onReady ,因为路由器必须提前解析异步路由组件才能正确调用组件挂钩... Vue SSR, Routing and Code-Splitting

所以不是

valueAboveLimit

尝试

app.$mount('#app');

希望这会有所帮助。