Nuxt/packages/server/src/jsdom.js

76 lines
2.1 KiB
JavaScript

import consola from 'consola'
import { timeout } from '@nuxt/utils'
export default async function renderAndGetWindow (
url = 'http://localhost:3000',
jsdomOpts = {},
{
loadedCallback,
loadingTimeout = 2000,
globals
} = {}
) {
const jsdom = await import('jsdom')
.then(m => m.default || m)
.catch((e) => {
consola.error(`
jsdom is not installed. Please install jsdom with:
$ yarn add --dev jsdom
OR
$ npm install --dev jsdom
`)
throw e
})
const options = Object.assign({
// Load subresources (https://github.com/tmpvar/jsdom#loading-subresources)
resources: 'usable',
runScripts: 'dangerously',
virtualConsole: true,
beforeParse (window) {
// Mock window.scrollTo
window.scrollTo = () => {}
}
}, jsdomOpts)
const jsdomErrHandler = (err) => {
throw err
}
if (options.virtualConsole) {
if (options.virtualConsole === true) {
options.virtualConsole = new jsdom.VirtualConsole().sendTo(consola)
}
// Throw error when window creation failed
options.virtualConsole.on('jsdomError', jsdomErrHandler)
} else {
// If we get the virtualConsole option as `false` we should delete for don't pass it to `jsdom.JSDOM.fromURL`
delete options.virtualConsole
}
const { window } = await jsdom.JSDOM.fromURL(url, options)
// If Nuxt could not be loaded (error from the server-side)
const nuxtExists = window.document.body.innerHTML.includes(`id="${globals.id}"`)
if (!nuxtExists) {
const error = new Error('Could not load the nuxt app')
error.body = window.document.body.innerHTML
window.close()
throw error
}
// Used by Nuxt to say when the components are loaded and the app ready
await timeout(new Promise((resolve) => {
window[loadedCallback] = () => resolve(window)
}), loadingTimeout, `Components loading in renderAndGetWindow was not completed in ${loadingTimeout / 1000}s`)
if (options.virtualConsole) {
// After window initialized successfully
options.virtualConsole.removeListener('jsdomError', jsdomErrHandler)
}
// Send back window object
return window
}