nuxt.render not working in production mode for Nuxt SPA - vuejs2

The following code runs in the standard Nuxt server/index.js just fine in development mode when starting up my SPA app.
// Init Nuxt.js
const nuxt = new Nuxt(config)
// Build only in dev mode
if (config.dev) {
const builder = new Builder(nuxt)
await builder.build()
}
// Give nuxt middleware to express
app.use(nuxt.render)
When deployed and in production mode, the build process is skipped (which is what I want) but nuxt.render() fails because it has not been initialized by builder.build().
I've tried everything I can think of and can't find a solution where it simply renders a pre-built app as it LOOKS like it is supposed to do.

Related

How to check if server build has been updated in SSR Nuxt application

I dont know how to solve the problem if SSR Nuxt app in browser is not compatible with server side build cause build has been updated. It means that user have old version of application in the browser and needs to refresh the page. I found something like this: https://dev-clone.nuxtjs.app/alejandroakbal/632139
So I have created pwa-update.js file in the plugins dir and register it in the nuxt.config.js.
But I dont see any console.log() in the console. Dont understand how to use it and if it is the right way to do it.
Implementaion looks like pwa-update.js
export default async (context) => {
const workbox = await window.$workbox;
if (!workbox) {
console.debug("Workbox couldn't be loaded.");
return;
} else {
console.log('Workbox has been loaded.'); // Dont see any message.
}
workbox.addEventListener('installed', (event) => {
if (!event.isUpdate) {
console.log('The PWA is on the latest version.');
return;
}
console.log('There is an update for the PWA, reloading...');
// window.location.reload();
});
};
nuxt.config.js
plugins: [
{ src: '~/plugins/pwa-update.js', mode: 'client' },
],
If you're regenerating your service worker using workbox during your development build process, a new service worker will be installed after every build. You can check this in your browser's dev tools. I believe the workbox generated service worker callls skipWaiting() in order to install new service workers immediately.
The client should get the new resources automagically because of webpack JS chunk name changes (assuming you're using webpack, the JS chunks it generates get new names after every new build, for cache busting purposes) and service worker version changes (workbox auto-increments service worker version, busting that cache as well). In other words, SSR or not, you won't need to worry about any version mismatches so long as you're using workbox to generate your service worker for you.

PWA InjectManifest workbox console / debug output suddenly disabled (Vue.js / Quasar Framework)

I'm building a PWA with Vue.js / Quasar Framework and recently added the PWA capability. I changed the "workboxPluginMode" property to "InjectManifest" and at first Workbox gave me debug / console as expected.
Also, the "custom-service-worker.js" definetly gets picked up by the process because it displays an error when i remove this line:
precacheAndRoute(self.__WB_MANIFEST)
So the file is recognized and actively using the defined caching strategies (i think), but it won't provide me any debug info or console.log's on console anymore. I really don't know what i have changed to do that.
My "custom-service-worker.js" looks like this:
import { precacheAndRoute } from 'workbox-precaching'
import { registerRoute } from 'workbox-routing'
import { StaleWhileRevalidate } from 'workbox-strategies'
console.log('custom service worker active')
// Use with precache injection
precacheAndRoute(self.__WB_MANIFEST)
// Caching strategies
registerRoute(
({url}) => {
console.log(url)
// url.pathname.startsWith('/images')
},
new StaleWhileRevalidate()
);
self.addEventListener('fetch', function(event) {
console.log(event)
event.respondWith(fetch(event.request));
})
I have no clue why, but the console debug output of workbox was only displayed in my default browser (Vivaldi). I wanted to work on plain Chromium because I couldn't install my PWA with Vivaldi (no installation prompt popped up), but that also works now. Have literally no explanation for this, but this is PWA development I guess, it is what it is. Anyways, problem solved for me.

How to use node server with Vue Vite bundler

Does someone know how to use Nodejs server instead of Vite own frontend dev server on the port 3000. I tried all command combinations like those below but with no success
vite
vite preview
vite preview --port:5000
Thanks
UPDATE Feb 8-th 2022
I have found a way. We have to add flag --watch to the vite build command, like: vite build --watch That way Vite will bundle only changes to the front-end and store it in the /dist folder but it will watch outside server like Nodejs. That way we can develop both front and back end file simultaneously and see the result immediately. We have to launch server file separately and serve index.html from there. If we use Nodejs and Express on the server side we also have to point default directory to be /dist because Vite will put bundled files there, like app.use(express.static(__dirname + '/dist'));. node will automatically serve index.html and other bundled files from this folder.
Basically you will set the middlewareMode to ssr on the server options:
const fs = require('fs')
const path = require('path')
const express = require('express')
const { createServer: createViteServer } = require('vite')
async function createServer() {
const app = express()
// Create Vite server in middleware mode. This disables Vite's own HTML
// serving logic and let the parent server take control.
//
// If you want to use Vite's own HTML serving logic (using Vite as
// a development middleware), using 'html' instead.
const vite = await createViteServer({
server: { middlewareMode: 'ssr' }
})
// use vite's connect instance as middleware
app.use(vite.middlewares)
app.use('*', async (req, res) => {
// serve index.html - we will tackle this next
})
app.listen(3000)
}
createServer()
This is explained in the doc: https://vitejs.dev/guide/ssr.html#setting-up-the-dev-server
Update for Vite 2.x
For Vite 2.x set server.middlewareMode to true and appType to custom:
// ...
const vite = await createViteServer({
server: { middlewareMode: true },
appType: 'custom'
})

How to refer other html file to load in production mode of application that are developed using electron?

I have problem in building electron application, which is made using electron.js and vue.js.
The development is almost done, so I need to build it and make production.
Basically, my project has license system, so when the program starts, users should activate it by entering license key. I wrote this part inside activate.html. So, inside public folder, there are two html files, one is default index.html, and the other is activate.html
Inside activate.html, when activation is success, startMain() javascript function is called. Inside this function, the program is navigated to main program, especially to index.html. This html file is Vue application, and then main program is started.
All this process is working fine in the development mode. But when it
comes to production, this is not working anymore. I probably know why this
happens, this is just because index.html is not available in
production mode when all these are built up.
Alternatively, I tried to load localhost:8080 inside
startMain(). But also this works fine in development mode, but unluckily, we don't have localhost server on production mode, so this
doesn't solve the problem.
This is startMain() inside activate.html
function startMain() {
window.__static = "index.html";
// Alternatively, we can use location.href on development mode.
// window.location.href = "http://localhost:8080/";
}
This is background.js ( electron main engine)
function createWindow() {
// Create the browser window.
win = new BrowserWindow({
width: 1400,
height: 900,
titleBarStyle: "hiddenInset"
});
win.setMenuBarVisibility(false);
if (isDevelopment) {
// Load the url of the dev server if in development mode
// win.loadURL(process.env.WEBPACK_DEV_SERVER_URL);
win.loadURL(`file://${process.cwd()}/public/activate.html`);
// if (!process.env.IS_TEST) win.webContents.openDevTools()
} else {
createProtocol("app");
// Load the index.html when not in development
win.loadFile("activate.html");
}
win.on("closed", () => {
win = null;
});
}
What I want is to make it run correctly in production mode.
Specifically, when the user finishes activation flow ( activate.html),
it should start main program ( index.html )
Please help me with this issue. I welcome any comments.
I built this application using vue-cli-plugin-electron-builder package
In Vue usually you use vue-router to switch between views. You set the BrowserWindow.location the first time, in background.js, but after that you are in the Vue app and you make router calls like this:
router.replace({ name: "index" }).catch(() => { });
It's hard to guess what to do in your case, without seeing the rest of your activate.html. You need to define router in your App and probably want to convert your activate.html into an activate.vue component and make it the proper first page of your App.
I think the cli-plugin boilerplate will call main.js where you will define your app and bootstraps it. You add router there:
import router from "./router";
window.$app = new Vue({
router,
In your bootstrap function you can also call something like router.replace({ name: "activate"}) to start your app with your activate vue component.

Use Express.js in an existing Nuxt.js project

I have a project built with Nuxt.js and I want to use express to be able to report bugsnag errors on my asyncData method etc.
How would I go to import that? I suppose is not as simple as npm install express --save.
I already have an api written in PHP so I would not use that as an api or anything else.
Is it overkill? Or is it a necessary evil? :D
To start using Express with an existing Nuxt project, you'll need to set up a simple server.js file that sets up your Express server and adds your Nuxt application as middleware. The only slight complication is setting it up to auto-rebuild in development. Here's a quick example server.js file that pulls in Nuxt and handles building when not in production.
const { Nuxt, Builder } = require('nuxt');
const app = require('express')();
// We instantiate Nuxt.js with the options
const isProd = process.env.NODE_ENV === 'production';
const config = require('./nuxt.config.js');
config.dev = !(isProd);
const nuxt = new Nuxt(config);
// No build in production
if (!isProd) {
const builder = new Builder(nuxt);
builder.build();
}
app.use(nuxt.render);
app.listen(3000);
console.log('Server is listening on http://localhost:3000');
You can then incorporate bugsnag as you normally would in express, I assume by requiring it and including it as middleware.
You dont need express to handle errors in asyncData. To handle errors in asyncData/fetch on ssr you just need to hook into render:errorMiddleware. See sentry plugin for nuxt for example
But it would only catch errors that happens on SSR. On client unfortunately that wont catch anything ( as well as express wont do anything for client). There is a bug for this in nuxt see here