簡體   English   中英

延遲加載的 vue-router 組件不適用於 SSR

[英]Lazy-Loaded vue-router components don't work with SSR

我有兩個不同的 server.js 和 client.js 入口點。(我正在使用 vue-server-renderer 和 laravel-mix) - (我的 server.js 和 client.js 看起來與這里描述的完全一樣 - spatie/laravel-服務器端渲染,如果我讓 static export 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 Output:

================ 錯誤 Output: ================ internal/modules/cjs/loader.js:628 throw err; ^

錯誤:找不到模塊 './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 Output:================ 錯誤 Output:======== ======== 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 Output:================ 錯誤 Output:======== ======== internal/modules/cjs/loader.js:628 throw err; ^ 錯誤:找不到模塊 './js/chunks/server/0.js?id=c3384f174123f0848451'

此外,如果我在renderVueComponentToString()中使用console.log(_dirname) ,它會返回“/”

我解決了它,現在它僅在客戶端與 SSR 和代碼拆分一起使用 - 如果您有更好的想法,我仍然全神貫注。

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

這是我的解決方案(以及我對 spatie/laravel-server-side-rendering 的更改):

我從charlesBochet 的評論中了解了如何分離捆綁包,但是我使用了一個而不是 2x 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);
        });
    });
  • 應用程序客戶端.js
router.onReady(function() {
    app.$mount('#app');
})
  • 最后路由器文件代碼拆分適用於 app-client.js
export const routes = [
{
    path: '/',
    name: "Home",
    component: () => import('../views/Home.vue')
},

不確定問題出在哪里,但您應該閱讀以下內容:

請注意,在返回/掛載應用程序之前,仍然需要在服務器和客戶端上使用router.onReady ,因為路由器必須提前解析異步路由組件才能正確調用組件內掛鈎...... Vue SSR,路由和代碼拆分

所以而不是

app.$mount('#app');

嘗試

router.onReady(() => {
  app.$mount('#app')
})

希望這可以幫助。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM