问题
I have two different entry points for server.js and client.js.(I'm using vue-server-renderer and laravel-mix) - (my server.js and client.js looks exactly like described here - spatie/laravel-server-side-rendering and if I make static export import Test from '../views/Test'
it works..
If I try importing the route without lazy loading, SSR works:
import Test from "../views/Test";
export const routes = [{
path: '/my-route',
name: "Test",
component: Test,
}]
But if I try lazy-loading, it fails on the SSR:
export const routes = [{
path: '/my-route',
name: "Test"
component: () => import('../views/Test.vue'),
}]
Cannot find module './js/chunks/server/0.js?id=c3384f174123f0848451'
For the () => import('../views/Home.vue)
, client.js works, only server.js doesn't work.
My 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);
});
});
The full error is:
The command "/usr/bin/node /home/vagrant/Code/project/storage/app/ssr/1228cfee3f79dc5949bd898950384e53.js" failed Exit Code: 1(General error)
Working directory: /home/vagrant/Code/project/public Output:
================ Error Output: ================ internal/modules/cjs/loader.js:628 throw err; ^
Error: Cannot find module './js/chunks/server/0.js?id=c3384f174123f0848451'
Update
I think I may have an idea why this is happening (I may be wrong):
export const routes = [{
path: '/',
name: "Home",
component: () => import('../views/Home')
}]
with this code, I get an error:
Error: Cannot find module './js/chunks/server/0.js?id=c3384f174123f0848451'
The command "/usr/bin/node /home/vagrant/Code/project/storage/app/ssr/717358e60bfd52035a1e58256cdfbba0.js" failed. Exit Code: 1(General error) Working directory: /home/vagrant/Code/project/public Output: ================ Error Output: ================ internal/modules/cjs/loader.js:628 throw err; ^ Error: Cannot find module './js/chunks/server/0.js?id=c3384f174123f0848451'
Look at the paths:
In my compiled file (which is at public/js
) I have this line:
var chunk = require("./js/chunks/server/" + ({}[chunkId]||chunkId) + ".js?id=" + {"0":"c3384f174123f0848451"}[chunkId] + "");
That seems like a relative path. However the file is actually running in what I specify in the config/ssr.php
- 'temp_path' => storage_path('app/ssr')
- so it cannot find the path.
However, even I change the temp_path
to public_path()
so that it can find the chunk from ./js/chunks/server/
(which is public/js/chunks/server/0.js
), it still throws the same error. Even though the SSR's temp_path is different.
The command "/usr/bin/node /home/vagrant/Code/project/public/3560d8d101faa4bdef316054b14873cc.js" failed. Exit Code: 1(General error) Working directory: /home/vagrant/Code/project/public Output: ================ Error Output: ================ internal/modules/cjs/loader.js:628 throw err; ^ Error: Cannot find module './js/chunks/server/0.js?id=c3384f174123f0848451'
Also if I console.log(_dirname)
in renderVueComponentToString()
it returns me '/'
回答1:
I solved it, now it works with SSR & code-splitting only in client-side - if you have any better idea I'm still all ears.
I used spatie/laravel-server-side-rendering and it's pretty easy to setup.
Here is my solution (and my changes on spatie/laravel-server-side-rendering):
I learn about separating bundles from charlesBochet's comment, however instead of 2x webpack.mix.js
files I used one.
- 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 - should wait for the router to be ready
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');
})
- and finally router file code-splitting works for app-client.js
export const routes = [
{
path: '/',
name: "Home",
component: () => import('../views/Home.vue')
},
回答2:
Not sure where the problem comes from, but you should read this :
Note that it is still necessary to use router.onReady on both server and client before returning / mounting the app, because the router must resolve async route components ahead of time in order to properly invoke in-component hooks ... Vue SSR, Routing and Code-Splitting
So instead of
app.$mount('#app');
Try
router.onReady(() => {
app.$mount('#app')
})
Hope this helps.
来源:https://stackoverflow.com/questions/58216963/lazy-loaded-vue-router-components-dont-work-with-ssr