mirror of
https://github.com/nuxt/nuxt.git
synced 2024-11-14 10:04:05 +00:00
76 lines
2.0 KiB
JavaScript
76 lines
2.0 KiB
JavaScript
|
import consola from 'consola'
|
||
|
import { timeout } from '@nuxt/common'
|
||
|
|
||
|
export default async function renderAndGetWindow(
|
||
|
url = 'http://localhost:3000',
|
||
|
jsdomOpts = {},
|
||
|
{
|
||
|
loadedCallback,
|
||
|
loadingTimeout = 2000,
|
||
|
ssr,
|
||
|
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)
|
||
|
}
|
||
|
|
||
|
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(
|
||
|
ssr ? `window.${globals.context}` : `<div id="${globals.id}">`
|
||
|
)
|
||
|
|
||
|
/* istanbul ignore if */
|
||
|
if (!nuxtExists) {
|
||
|
const error = new Error('Could not load the nuxt app')
|
||
|
error.body = window.document.body.innerHTML
|
||
|
throw error
|
||
|
}
|
||
|
|
||
|
// Used by Nuxt.js 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 ${timeout / 1000}s`)
|
||
|
|
||
|
if (options.virtualConsole) {
|
||
|
// After window initialized successfully
|
||
|
options.virtualConsole.removeListener('jsdomError', jsdomErrHandler)
|
||
|
}
|
||
|
|
||
|
// Send back window object
|
||
|
return window
|
||
|
}
|