mirror of
https://github.com/nuxt/nuxt.git
synced 2024-11-23 14:15:13 +00:00
parent
03178b73cd
commit
ef41e205e6
@ -58,6 +58,7 @@
|
||||
"@nuxt/cli": "2.4.5",
|
||||
"@nuxt/core": "2.4.5",
|
||||
"@nuxt/generator": "2.4.5",
|
||||
"@nuxt/loading-screen": "^0.0.2",
|
||||
"@nuxt/opencollective": "^0.2.1",
|
||||
"@nuxt/webpack": "2.4.5"
|
||||
},
|
||||
|
@ -20,13 +20,8 @@ export default {
|
||||
|
||||
async run(cmd) {
|
||||
const { argv } = cmd
|
||||
const nuxt = await this.startDev(cmd, argv)
|
||||
|
||||
// Opens the server listeners url in the default browser
|
||||
if (argv.open) {
|
||||
const openerPromises = nuxt.server.listeners.map(listener => opener(listener.url))
|
||||
await Promise.all(openerPromises)
|
||||
}
|
||||
await this.startDev(cmd, argv, argv.open)
|
||||
},
|
||||
|
||||
async startDev(cmd, argv) {
|
||||
@ -47,21 +42,28 @@ export default {
|
||||
nuxt.hook('watch:restart', payload => this.onWatchRestart(payload, { nuxt, builder, cmd, argv }))
|
||||
nuxt.hook('bundler:change', changedFileName => this.onBundlerChange(changedFileName))
|
||||
|
||||
// Create builder instance
|
||||
const builder = await cmd.getBuilder(nuxt)
|
||||
|
||||
// Wait for nuxt to be ready
|
||||
await nuxt.ready()
|
||||
|
||||
// Start listening
|
||||
await nuxt.server.listen()
|
||||
|
||||
// Show banner when listening
|
||||
showBanner(nuxt)
|
||||
|
||||
// Opens the server listeners url in the default browser (only once)
|
||||
if (argv.open) {
|
||||
argv.open = false
|
||||
const openerPromises = nuxt.server.listeners.map(listener => opener(listener.url))
|
||||
await Promise.all(openerPromises)
|
||||
}
|
||||
|
||||
// Create builder instance
|
||||
const builder = await cmd.getBuilder(nuxt)
|
||||
|
||||
// Start Build
|
||||
await builder.build()
|
||||
|
||||
// Show banner after build
|
||||
showBanner(nuxt)
|
||||
|
||||
// Return instance
|
||||
return nuxt
|
||||
},
|
||||
|
@ -30,7 +30,7 @@ export function colorize(text) {
|
||||
.replace(/\[[^ ]+]/g, m => chalk.grey(m))
|
||||
.replace(/<[^ ]+>/g, m => chalk.green(m))
|
||||
.replace(/ (-[-\w,]+)/g, m => chalk.bold(m))
|
||||
.replace(/`(.+)`/g, (_, m) => chalk.bold.cyan(m))
|
||||
.replace(/`([^`]+)`/g, (_, m) => chalk.bold.cyan(m))
|
||||
}
|
||||
|
||||
export function box(message, title, options) {
|
||||
|
@ -51,7 +51,7 @@ describe('dev', () => {
|
||||
// Test error on second build so we cover oldInstance stuff
|
||||
const builder = new Builder()
|
||||
builder.nuxt = new Nuxt()
|
||||
Builder.prototype.build = jest.fn().mockImplementationOnce(() => Promise.reject(new Error('Build Error')))
|
||||
Builder.prototype.build = () => { throw new Error('Build Error') }
|
||||
await Nuxt.fileRestartHook(builder)
|
||||
|
||||
expect(Nuxt.prototype.close).toHaveBeenCalled()
|
||||
|
@ -330,5 +330,10 @@ export function getNuxtConfig(_options) {
|
||||
bundleRenderer.runInNewContext = options.dev
|
||||
}
|
||||
|
||||
// Add loading screen
|
||||
if (options.dev) {
|
||||
options.devModules.push('@nuxt/loading-screen')
|
||||
}
|
||||
|
||||
return options
|
||||
}
|
||||
|
@ -12,6 +12,13 @@ export default ({ options, nuxt, renderRoute, resources }) => async function nux
|
||||
const url = decodeURI(req.url)
|
||||
res.statusCode = 200
|
||||
const result = await renderRoute(url, context)
|
||||
|
||||
// If result is falsy, call renderLoading
|
||||
if (!result) {
|
||||
await nuxt.callHook('server:nuxt:renderLoading', req, res)
|
||||
return
|
||||
}
|
||||
|
||||
await nuxt.callHook('render:route', url, result, context)
|
||||
const {
|
||||
html,
|
||||
|
@ -115,6 +115,7 @@ export default class Server {
|
||||
context: this.renderer.context
|
||||
}))
|
||||
|
||||
// Dev middleware
|
||||
if (this.options.dev) {
|
||||
this.useMiddleware((req, res, next) => {
|
||||
if (!this.devMiddleware) {
|
||||
|
@ -2,15 +2,16 @@
|
||||
<div>
|
||||
<section class="Landscape">
|
||||
<div class="Landscape__Logo">
|
||||
<div class="VueToNuxtLogo">
|
||||
<div class="Triangle Triangle--two"></div>
|
||||
<div class="Triangle Triangle--one"></div>
|
||||
<div class="Triangle Triangle--three"></div>
|
||||
<div class="Triangle Triangle--four"></div>
|
||||
</div>
|
||||
<h1 class="Landscape__Logo__Title">NUXT</h1>
|
||||
<svg class="logo" width="220" height="166" xmlns="http://www.w3.org/2000/svg">
|
||||
<g transform="translate(-18 -29)" fill="none" fill-rule="evenodd">
|
||||
<path d="M0 176h67.883a22.32 22.32 0 0 1 2.453-7.296L134 57.718 100.881 0 0 176zM218.694 176H250L167.823 32 153 58.152l62.967 110.579a21.559 21.559 0 0 1 2.727 7.269z" />
|
||||
<path d="M86.066 189.388a8.241 8.241 0 0 1-.443-.908 11.638 11.638 0 0 1-.792-6.566H31.976l78.55-138.174 33.05 58.932L154 94.882l-32.69-58.64C120.683 35.1 116.886 29 110.34 29c-2.959 0-7.198 1.28-10.646 7.335L20.12 176.185c-.676 1.211-3.96 7.568-.7 13.203C20.912 191.95 24.08 195 31.068 195h66.646c-6.942 0-10.156-3.004-11.647-5.612z" fill="#00C58E" />
|
||||
<path d="M235.702 175.491L172.321 62.216c-.655-1.191-4.313-7.216-10.68-7.216-2.868 0-6.977 1.237-10.32 7.193L143 75.706v26.104l18.709-32.31 62.704 111.626h-23.845c.305 1.846.134 3.74-.496 5.498a7.06 7.06 0 0 1-.497 1.122l-.203.413c-3.207 5.543-10.139 5.841-11.494 5.841h37.302c1.378 0 8.287-.298 11.493-5.841 1.423-2.52 2.439-6.758-.97-12.668z" fill="#108775" />
|
||||
<path d="M201.608 189.07l.21-.418c.206-.364.378-.745.515-1.139a10.94 10.94 0 0 0 .515-5.58 16.938 16.938 0 0 0-2.152-5.72l-49.733-87.006L143.5 76h-.136l-7.552 13.207-49.71 87.006a17.534 17.534 0 0 0-1.917 5.72c-.4 2.21-.148 4.486.725 6.557.13.31.278.613.444.906 1.497 2.558 4.677 5.604 11.691 5.604h92.592c1.473 0 8.651-.302 11.971-5.93zm-58.244-86.657l45.455 79.52H97.934l45.43-79.52z" fill="#2F4A5F" fill-rule="nonzero" />
|
||||
</g>
|
||||
</svg>
|
||||
</div>
|
||||
<h2 class="Landscape__Title">The Vue Framework</h2>
|
||||
<h2 class="Landscape__Title">The Vue.js Framework</h2>
|
||||
<a href="https://nuxtjs.org/guide/installation#starting-from-scratch" target="_blank" class="button">
|
||||
Get Started
|
||||
</a>
|
||||
@ -85,75 +86,6 @@
|
||||
}
|
||||
}
|
||||
|
||||
.VueToNuxtLogo {
|
||||
display: inline-block;
|
||||
animation: turn 2s linear forwards;
|
||||
transform: rotateX(180deg);
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
height: 180px;
|
||||
width: 245px;
|
||||
}
|
||||
|
||||
.Triangle {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 0;
|
||||
height: 0;
|
||||
}
|
||||
|
||||
.Triangle--one {
|
||||
border-left: 105px solid transparent;
|
||||
border-right: 105px solid transparent;
|
||||
border-bottom: 180px solid #41B883;
|
||||
}
|
||||
|
||||
.Triangle--two {
|
||||
top: 30px;
|
||||
left: 35px;
|
||||
animation: goright 0.5s linear forwards 2.5s;
|
||||
border-left: 87.5px solid transparent;
|
||||
border-right: 87.5px solid transparent;
|
||||
border-bottom: 150px solid #3B8070;
|
||||
}
|
||||
|
||||
.Triangle--three {
|
||||
top: 60px;
|
||||
left: 35px;
|
||||
animation: goright 0.5s linear forwards 2.5s;
|
||||
border-left: 70px solid transparent;
|
||||
border-right: 70px solid transparent;
|
||||
border-bottom: 120px solid #35495E;
|
||||
}
|
||||
|
||||
.Triangle--four {
|
||||
top: 120px;
|
||||
left: 70px;
|
||||
animation: godown 0.5s linear forwards 2s;
|
||||
border-left: 35px solid transparent;
|
||||
border-right: 35px solid transparent;
|
||||
border-bottom: 60px solid #fff;
|
||||
}
|
||||
|
||||
@keyframes turn {
|
||||
100% {
|
||||
transform: rotateX(0deg);
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes godown {
|
||||
100% {
|
||||
top: 180px;
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes goright {
|
||||
100% {
|
||||
left: 70px;
|
||||
}
|
||||
}
|
||||
|
||||
.button {
|
||||
font-family: "Quicksand", "Source Sans Pro", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
|
||||
position: relative;
|
||||
|
@ -1,6 +1,6 @@
|
||||
<style>
|
||||
body, html, #<%= globals.id %> {
|
||||
background: <%= options.background %>;
|
||||
background: <%= (options.theme === 'dark' ? '#2F4A5F' : 'white') %>;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
display: flex;
|
||||
@ -9,75 +9,51 @@ body, html, #<%= globals.id %> {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.logo {
|
||||
animation: turn 2s linear forwards 1s;
|
||||
transform: rotateX(180deg);
|
||||
#nuxt-loading {
|
||||
animation: opacity 1s ease-in-out;
|
||||
animation-fill-mode: forwards;
|
||||
animation-delay: 1s;
|
||||
opacity: 0;
|
||||
}
|
||||
#nuxt-loading .logo {
|
||||
position: relative;
|
||||
height: 346px;
|
||||
width: 536px;
|
||||
height: 166px;
|
||||
width: 220px;
|
||||
}
|
||||
|
||||
.triangle {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 0;
|
||||
height: 0;
|
||||
#nuxt-loading-status {
|
||||
font-family: sans-serif;
|
||||
font-weight: 500;
|
||||
text-align: center;
|
||||
color: <%= (options.theme === 'dark' ? 'white' : '#2F4A5F') %>;
|
||||
}
|
||||
.triangle--one {
|
||||
border-left: 210px solid transparent;
|
||||
border-right: 210px solid transparent;
|
||||
border-bottom: 360px solid #41B883;
|
||||
#nuxt-loading-status.errored {
|
||||
color: <%= (options.theme === 'dark' ? '#da6371' : '#D0021B') %>;
|
||||
}
|
||||
.triangle--two {
|
||||
top: 60px;
|
||||
left: 70px;
|
||||
animation: goright 0.5s linear forwards 3.5s;
|
||||
border-left: 175px solid transparent;
|
||||
border-right: 175px solid transparent;
|
||||
border-bottom: 300px solid #3B8070;
|
||||
}
|
||||
.triangle--three {
|
||||
top: 120px;
|
||||
left: 70px;
|
||||
animation: goright 0.5s linear forwards 3.5s;
|
||||
border-left: 140px solid transparent;
|
||||
border-right: 140px solid transparent;
|
||||
border-bottom: 240px solid #35495E;
|
||||
}
|
||||
.triangle--four {
|
||||
top: 240px;
|
||||
left: 140px;
|
||||
animation: godown 0.5s linear forwards 3s;
|
||||
border-left: 70px solid transparent;
|
||||
border-right: 70px solid transparent;
|
||||
border-bottom: 120px solid #fff;
|
||||
}
|
||||
|
||||
@keyframes turn {
|
||||
@keyframes opacity {
|
||||
100% {
|
||||
transform: rotateX(0deg);
|
||||
}
|
||||
}
|
||||
@keyframes godown {
|
||||
100% {
|
||||
top: 360px;
|
||||
}
|
||||
}
|
||||
@keyframes goright {
|
||||
100% {
|
||||
left: 140px;
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
<div class="logo">
|
||||
<div class="triangle triangle--two"></div>
|
||||
<div class="triangle triangle--one"></div>
|
||||
<div class="triangle triangle--three"></div>
|
||||
<div class="triangle triangle--four"></div>
|
||||
<div id="nuxt-loading">
|
||||
<svg class="logo" width="220" height="166" xmlns="http://www.w3.org/2000/svg">
|
||||
<g transform="translate(-18 -29)" fill="none" fill-rule="evenodd">
|
||||
<path d="M0 176h67.883a22.32 22.32 0 0 1 2.453-7.296L134 57.718 100.881 0 0 176zM218.694 176H250L167.823 32 153 58.152l62.967 110.579a21.559 21.559 0 0 1 2.727 7.269z" />
|
||||
<path d="M86.066 189.388a8.241 8.241 0 0 1-.443-.908 11.638 11.638 0 0 1-.792-6.566H31.976l78.55-138.174 33.05 58.932L154 94.882l-32.69-58.64C120.683 35.1 116.886 29 110.34 29c-2.959 0-7.198 1.28-10.646 7.335L20.12 176.185c-.676 1.211-3.96 7.568-.7 13.203C20.912 191.95 24.08 195 31.068 195h66.646c-6.942 0-10.156-3.004-11.647-5.612z" fill="#00C58E" />
|
||||
<path d="M235.702 175.491L172.321 62.216c-.655-1.191-4.313-7.216-10.68-7.216-2.868 0-6.977 1.237-10.32 7.193L143 75.706v26.104l18.709-32.31 62.704 111.626h-23.845c.305 1.846.134 3.74-.496 5.498a7.06 7.06 0 0 1-.497 1.122l-.203.413c-3.207 5.543-10.139 5.841-11.494 5.841h37.302c1.378 0 8.287-.298 11.493-5.841 1.423-2.52 2.439-6.758-.97-12.668z" fill="#108775" />
|
||||
<path d="M201.608 189.07l.21-.418c.206-.364.378-.745.515-1.139a10.94 10.94 0 0 0 .515-5.58 16.938 16.938 0 0 0-2.152-5.72l-49.733-87.006L143.5 76h-.136l-7.552 13.207-49.71 87.006a17.534 17.534 0 0 0-1.917 5.72c-.4 2.21-.148 4.486.725 6.557.13.31.278.613.444.906 1.497 2.558 4.677 5.604 11.691 5.604h92.592c1.473 0 8.651-.302 11.971-5.93zm-58.244-86.657l45.455 79.52H97.934l45.43-79.52z" fill="<%= (options.theme === 'dark' ? 'white' : '#2F4A5F') %>" fill-rule="nonzero" />
|
||||
</g>
|
||||
</svg>
|
||||
<h3 id="nuxt-loading-status">Loading...</h3>
|
||||
</div>
|
||||
|
||||
|
||||
<!-- https://codepen.io/alexchopin/pen/jBWrej -->
|
||||
<script>
|
||||
window.addEventListener('error', function () {
|
||||
var e = document.getElementById('nuxt-loading-status');
|
||||
if (e) {
|
||||
e.innerHTML = 'An error occurred';
|
||||
e.className += 'errored'
|
||||
}
|
||||
});
|
||||
</script>
|
||||
|
@ -5,7 +5,7 @@ import consola from 'consola'
|
||||
import devalue from '@nuxt/devalue'
|
||||
import invert from 'lodash/invert'
|
||||
import template from 'lodash/template'
|
||||
import { waitFor, isUrl, urlJoin } from '@nuxt/utils'
|
||||
import { isUrl, urlJoin } from '@nuxt/utils'
|
||||
import { createBundleRenderer } from 'vue-server-renderer'
|
||||
|
||||
import SPAMetaRenderer from './spa-meta'
|
||||
@ -33,9 +33,6 @@ export default class VueRenderer {
|
||||
spaTemplate: undefined,
|
||||
errorTemplate: this.parseTemplate('Nuxt.js Internal Server Error')
|
||||
})
|
||||
|
||||
// Keep time of last shown messages
|
||||
this._lastWaitingForResource = new Date()
|
||||
}
|
||||
|
||||
get assetsMapping() {
|
||||
@ -46,6 +43,7 @@ export default class VueRenderer {
|
||||
const legacyAssets = this.context.resources.clientManifest.assetsMapping
|
||||
const modernAssets = invert(this.context.resources.modernManifest.assetsMapping)
|
||||
const mapping = {}
|
||||
|
||||
for (const legacyJsFile in legacyAssets) {
|
||||
const chunkNamesHash = legacyAssets[legacyJsFile]
|
||||
mapping[legacyJsFile] = modernAssets[chunkNamesHash]
|
||||
@ -53,12 +51,14 @@ export default class VueRenderer {
|
||||
delete this.context.resources.clientManifest.assetsMapping
|
||||
delete this.context.resources.modernManifest.assetsMapping
|
||||
this._assetsMapping = mapping
|
||||
|
||||
return mapping
|
||||
}
|
||||
|
||||
renderScripts(context) {
|
||||
if (this.context.options.modern === 'client') {
|
||||
const scriptPattern = /<script[^>]*?src="([^"]*?)"[^>]*?>[^<]*?<\/script>/g
|
||||
|
||||
return context.renderScripts().replace(scriptPattern, (scriptTag, jsFile) => {
|
||||
const legacyJsFile = jsFile.replace(this.publicPath, '')
|
||||
const modernJsFile = this.assetsMapping[legacyJsFile]
|
||||
@ -70,14 +70,17 @@ export default class VueRenderer {
|
||||
.replace(legacyJsFile, modernJsFile)
|
||||
: ''
|
||||
const noModuleTag = scriptTag.replace('<script', `<script nomodule${cors}`)
|
||||
|
||||
return noModuleTag + moduleTag
|
||||
})
|
||||
}
|
||||
|
||||
return context.renderScripts()
|
||||
}
|
||||
|
||||
getModernFiles(legacyFiles = []) {
|
||||
const modernFiles = []
|
||||
|
||||
for (const legacyJsFile of legacyFiles) {
|
||||
const modernFile = { ...legacyJsFile, modern: true }
|
||||
if (modernFile.asType === 'script') {
|
||||
@ -87,11 +90,13 @@ export default class VueRenderer {
|
||||
}
|
||||
modernFiles.push(modernFile)
|
||||
}
|
||||
|
||||
return modernFiles
|
||||
}
|
||||
|
||||
getSsrPreloadFiles(context) {
|
||||
const preloadFiles = context.getPreloadFiles()
|
||||
|
||||
// In eligible server modern mode, preloadFiles are modern bundles from modern renderer
|
||||
return this.context.options.modern === 'client' ? this.getModernFiles(preloadFiles) : preloadFiles
|
||||
}
|
||||
@ -99,6 +104,7 @@ export default class VueRenderer {
|
||||
renderSsrResourceHints(context) {
|
||||
if (this.context.options.modern === 'client') {
|
||||
const linkPattern = /<link[^>]*?href="([^"]*?)"[^>]*?as="script"[^>]*?>/g
|
||||
|
||||
return context.renderResourceHints().replace(linkPattern, (linkTag, jsFile) => {
|
||||
const legacyJsFile = jsFile.replace(this.publicPath, '')
|
||||
const modernJsFile = this.assetsMapping[legacyJsFile]
|
||||
@ -110,6 +116,7 @@ export default class VueRenderer {
|
||||
return linkTag.replace('rel="preload"', `rel="modulepreload"${cors}`).replace(legacyJsFile, modernJsFile)
|
||||
})
|
||||
}
|
||||
|
||||
return context.renderResourceHints()
|
||||
}
|
||||
|
||||
@ -119,6 +126,9 @@ export default class VueRenderer {
|
||||
}
|
||||
this._readyCalled = true
|
||||
|
||||
// Resolve dist path
|
||||
this.distPath = path.resolve(this.context.options.buildDir, 'dist', 'server')
|
||||
|
||||
// -- Development mode --
|
||||
if (this.context.options.dev) {
|
||||
this.context.nuxt.hook('build:resources', mfs => this.loadResources(mfs))
|
||||
@ -137,14 +147,13 @@ export default class VueRenderer {
|
||||
}
|
||||
|
||||
// Verify resources
|
||||
if (!this.isReady) {
|
||||
if (this.context.options.modern && !this.isModernReady) {
|
||||
throw new Error(
|
||||
'No build files found. Use either `nuxt build` or `builder.build()` or start nuxt in development mode.'
|
||||
`No modern build files found in ${this.distPath}.\nUse either \`nuxt build --modern\` or \`modern\` option to build modern files.`
|
||||
)
|
||||
}
|
||||
if (this.context.options.modern && !this.context.resources.modernManifest) {
|
||||
} else if (!this.isReady) {
|
||||
throw new Error(
|
||||
'No modern build files found. Use either `nuxt build --modern` or `modern` option to build modern files.'
|
||||
`No build files found in ${this.distPath}.\nUse either \`nuxt build\` or \`builder.build()\` or start nuxt in development mode.`
|
||||
)
|
||||
}
|
||||
|
||||
@ -152,16 +161,17 @@ export default class VueRenderer {
|
||||
}
|
||||
|
||||
async loadResources(_fs) {
|
||||
const distPath = path.resolve(this.context.options.buildDir, 'dist', 'server')
|
||||
const updated = []
|
||||
|
||||
const readResource = async (fileName, encoding) => {
|
||||
try {
|
||||
const fullPath = path.resolve(distPath, fileName)
|
||||
const fullPath = path.resolve(this.distPath, fileName)
|
||||
|
||||
if (!await _fs.exists(fullPath)) {
|
||||
return
|
||||
}
|
||||
const contents = await _fs.readFile(fullPath, encoding)
|
||||
|
||||
return contents
|
||||
} catch (err) {
|
||||
consola.error('Unable to load resource:', fileName, err)
|
||||
@ -204,12 +214,14 @@ export default class VueRenderer {
|
||||
|
||||
// Call resourcesLoaded hook
|
||||
consola.debug('Resources loaded:', updated.join(','))
|
||||
|
||||
return this.context.nuxt.callHook('render:resourcesLoaded', this.context.resources)
|
||||
}
|
||||
|
||||
async loadTemplates() {
|
||||
// Reload error template
|
||||
const errorTemplatePath = path.resolve(this.context.options.buildDir, 'views/error.html')
|
||||
|
||||
if (await fs.exists(errorTemplatePath)) {
|
||||
const errorTemplate = await fs.readFile(errorTemplatePath, 'utf8')
|
||||
this.context.resources.errorTemplate = this.parseTemplate(errorTemplate)
|
||||
@ -217,6 +229,7 @@ export default class VueRenderer {
|
||||
|
||||
// Reload loading template
|
||||
const loadingHTMLPath = path.resolve(this.context.options.buildDir, 'loading.html')
|
||||
|
||||
if (await fs.exists(loadingHTMLPath)) {
|
||||
this.context.resources.loadingHTML = await fs.readFile(loadingHTMLPath, 'utf8')
|
||||
this.context.resources.loadingHTML = this.context.resources.loadingHTML.replace(/\r|\n|[\t\s]{3,}/g, '')
|
||||
@ -248,6 +261,10 @@ export default class VueRenderer {
|
||||
return true
|
||||
}
|
||||
|
||||
get isModernReady() {
|
||||
return this.isReady && this.context.resources.modernManifest
|
||||
}
|
||||
|
||||
// TODO: Remove in Nuxt 3
|
||||
get isResourcesAvailable() { /* Backward compatibility */
|
||||
return this.isReady
|
||||
@ -420,25 +437,26 @@ export default class VueRenderer {
|
||||
}
|
||||
}
|
||||
|
||||
async renderRoute(url, context = {}, retries = 5) {
|
||||
_throwNotReadyError() {
|
||||
const error = new Error()
|
||||
|
||||
error.statusCode = 500
|
||||
if (!this._readyCalled) {
|
||||
error.message = 'Nuxt is not initialized! `nuxt.ready()` should be called.'
|
||||
} else {
|
||||
error.message = `SSR renderer is not initialized! Please check ${this.distPath} existence.`
|
||||
}
|
||||
throw error
|
||||
}
|
||||
|
||||
async renderRoute(url, context = {}) {
|
||||
/* istanbul ignore if */
|
||||
if (!this.isReady) {
|
||||
if (!this._readyCalled) {
|
||||
throw new Error('Nuxt is not initialized! `nuxt.ready()` should be called!')
|
||||
if (!this.context.options.dev) {
|
||||
return this._throwNotReadyError()
|
||||
}
|
||||
|
||||
if (!this.context.options.dev || retries <= 0) {
|
||||
throw new Error('Server resources are not available!')
|
||||
}
|
||||
|
||||
const now = new Date()
|
||||
if (now - this._lastWaitingForResource > 3000) {
|
||||
consola.info('Waiting for server resources...')
|
||||
this._lastWaitingForResource = now
|
||||
}
|
||||
await waitFor(1000)
|
||||
|
||||
return this.renderRoute(url, context, retries - 1)
|
||||
// Tell nuxt middleware to render UI
|
||||
return false
|
||||
}
|
||||
|
||||
// Log rendered url
|
||||
|
@ -385,6 +385,9 @@ export default class WebpackBaseConfig {
|
||||
},
|
||||
allDone: () => {
|
||||
nuxt.callHook('bundler:done')
|
||||
},
|
||||
progress({ statesArray }) {
|
||||
nuxt.callHook('bundler:progress', statesArray)
|
||||
}
|
||||
}
|
||||
}))
|
||||
|
@ -1,6 +1,6 @@
|
||||
import path from 'path'
|
||||
import consola from 'consola'
|
||||
import { Builder, BundleBuilder, getPort, loadFixture, Nuxt, rp } from '../utils'
|
||||
import { Builder, BundleBuilder, getPort, loadFixture, Nuxt, rp, waitFor } from '../utils'
|
||||
|
||||
let port
|
||||
const url = route => 'http://localhost:' + port + route
|
||||
@ -50,9 +50,15 @@ describe('basic dev', () => {
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
nuxt = new Nuxt(config)
|
||||
await nuxt.ready()
|
||||
|
||||
builder = new Builder(nuxt, BundleBuilder)
|
||||
|
||||
await builder.build()
|
||||
await waitFor(2000) // TODO: Find a better way
|
||||
|
||||
port = await getPort()
|
||||
await nuxt.server.listen(port, 'localhost')
|
||||
})
|
||||
|
@ -1,9 +1,8 @@
|
||||
import path from 'path'
|
||||
import consola from 'consola'
|
||||
import { Nuxt } from '../utils'
|
||||
|
||||
const NO_BUILD_MSG = 'No build files found. Use either `nuxt build` or `builder.build()` or start nuxt in development mode.'
|
||||
const NO_MODERN_BUILD_MSG = 'No modern build files found. Use either `nuxt build --modern` or `modern` option to build modern files.'
|
||||
const NO_BUILD_MSG = /Use either `nuxt build` or `builder\.build\(\)` or start nuxt in development mode/
|
||||
const NO_MODERN_BUILD_MSG = /Use either `nuxt build --modern` or `modern` option to build modern files/
|
||||
|
||||
describe('renderer', () => {
|
||||
afterEach(() => {
|
||||
@ -19,7 +18,9 @@ describe('renderer', () => {
|
||||
})
|
||||
await nuxt.ready()
|
||||
await expect(nuxt.renderer.renderer.isReady).toBe(false)
|
||||
expect(consola.fatal).toHaveBeenCalledWith(new Error(NO_BUILD_MSG))
|
||||
expect(consola.fatal).toHaveBeenCalledWith(expect.objectContaining({
|
||||
message: expect.stringMatching(NO_BUILD_MSG)
|
||||
}))
|
||||
})
|
||||
|
||||
test('detect no-build (SPA)', async () => {
|
||||
@ -31,7 +32,9 @@ describe('renderer', () => {
|
||||
})
|
||||
await nuxt.ready()
|
||||
await expect(nuxt.renderer.renderer.isReady).toBe(false)
|
||||
expect(consola.fatal).toHaveBeenCalledWith(new Error(NO_BUILD_MSG))
|
||||
expect(consola.fatal).toHaveBeenCalledWith(expect.objectContaining({
|
||||
message: expect.stringMatching(NO_BUILD_MSG)
|
||||
}))
|
||||
})
|
||||
test('detect no-modern-build', async () => {
|
||||
const nuxt = new Nuxt({
|
||||
@ -39,10 +42,12 @@ describe('renderer', () => {
|
||||
mode: 'universal',
|
||||
modern: 'client',
|
||||
dev: false,
|
||||
buildDir: path.resolve(__dirname, '..', 'fixtures', 'empty', '.nuxt')
|
||||
buildDir: '/path/to/404'
|
||||
})
|
||||
await nuxt.ready()
|
||||
await expect(nuxt.renderer.renderer.isReady).toBe(true)
|
||||
expect(consola.fatal).toHaveBeenCalledWith(new Error(NO_MODERN_BUILD_MSG))
|
||||
await expect(nuxt.renderer.renderer.isModernReady).toBe(false)
|
||||
expect(consola.fatal).toHaveBeenCalledWith(expect.objectContaining({
|
||||
message: expect.stringMatching(NO_MODERN_BUILD_MSG)
|
||||
}))
|
||||
})
|
||||
})
|
||||
|
12
yarn.lock
12
yarn.lock
@ -1585,6 +1585,16 @@
|
||||
error-stack-parser "^2.0.0"
|
||||
string-width "^2.0.0"
|
||||
|
||||
"@nuxt/loading-screen@^0.0.2":
|
||||
version "0.0.2"
|
||||
resolved "https://registry.npmjs.org/@nuxt/loading-screen/-/loading-screen-0.0.2.tgz#c3ba3b408c4af93998b1a99c33dddc4b6e3114e9"
|
||||
integrity sha512-/DDpjzlLxlTciVafjF5VS5oJFZAirXryzTfT6yQE/rSl0bEFOsa5Xm/N+NYoHmnp3HfYyYfl7IzOVBLQ5IUM8w==
|
||||
dependencies:
|
||||
connect "^3.6.6"
|
||||
fs-extra "^7.0.1"
|
||||
serve-static "^1.13.2"
|
||||
ws "^6.2.0"
|
||||
|
||||
"@nuxt/opencollective@^0.2.1":
|
||||
version "0.2.1"
|
||||
resolved "https://registry.npmjs.org/@nuxt/opencollective/-/opencollective-0.2.1.tgz#8290f1220072637e575c3935733719a78ad2d056"
|
||||
@ -11733,7 +11743,7 @@ ws@^5.2.0:
|
||||
dependencies:
|
||||
async-limiter "~1.0.0"
|
||||
|
||||
ws@^6.0.0, ws@^6.1.0, ws@^6.1.2:
|
||||
ws@^6.0.0, ws@^6.1.0, ws@^6.1.2, ws@^6.2.0:
|
||||
version "6.2.0"
|
||||
resolved "https://registry.npmjs.org/ws/-/ws-6.2.0.tgz#13806d9913b2a5f3cbb9ba47b563c002cbc7c526"
|
||||
integrity sha512-deZYUNlt2O4buFCa3t5bKLf8A7FPP/TVjwOeVNpw818Ma5nk4MLXls2eoEGS39o8119QIYxTrTDoPQ5B/gTD6w==
|
||||
|
Loading…
Reference in New Issue
Block a user