Skip to content

Commit ef41e20

Browse files
Sébastien Chopinpi0
authored andcommitted
feat: loading screen (nuxt#5251)
[release]
1 parent 03178b7 commit ef41e20

14 files changed

Lines changed: 156 additions & 190 deletions

File tree

distributions/nuxt/package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,7 @@
5858
"@nuxt/cli": "2.4.5",
5959
"@nuxt/core": "2.4.5",
6060
"@nuxt/generator": "2.4.5",
61+
"@nuxt/loading-screen": "^0.0.2",
6162
"@nuxt/opencollective": "^0.2.1",
6263
"@nuxt/webpack": "2.4.5"
6364
},

packages/cli/src/commands/dev.js

Lines changed: 14 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -20,13 +20,8 @@ export default {
2020

2121
async run(cmd) {
2222
const { argv } = cmd
23-
const nuxt = await this.startDev(cmd, argv)
2423

25-
// Opens the server listeners url in the default browser
26-
if (argv.open) {
27-
const openerPromises = nuxt.server.listeners.map(listener => opener(listener.url))
28-
await Promise.all(openerPromises)
29-
}
24+
await this.startDev(cmd, argv, argv.open)
3025
},
3126

3227
async startDev(cmd, argv) {
@@ -47,21 +42,28 @@ export default {
4742
nuxt.hook('watch:restart', payload => this.onWatchRestart(payload, { nuxt, builder, cmd, argv }))
4843
nuxt.hook('bundler:change', changedFileName => this.onBundlerChange(changedFileName))
4944

50-
// Create builder instance
51-
const builder = await cmd.getBuilder(nuxt)
52-
5345
// Wait for nuxt to be ready
5446
await nuxt.ready()
5547

5648
// Start listening
5749
await nuxt.server.listen()
5850

51+
// Show banner when listening
52+
showBanner(nuxt)
53+
54+
// Opens the server listeners url in the default browser (only once)
55+
if (argv.open) {
56+
argv.open = false
57+
const openerPromises = nuxt.server.listeners.map(listener => opener(listener.url))
58+
await Promise.all(openerPromises)
59+
}
60+
61+
// Create builder instance
62+
const builder = await cmd.getBuilder(nuxt)
63+
5964
// Start Build
6065
await builder.build()
6166

62-
// Show banner after build
63-
showBanner(nuxt)
64-
6567
// Return instance
6668
return nuxt
6769
},

packages/cli/src/utils/formatting.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ export function colorize(text) {
3030
.replace(/\[[^ ]+]/g, m => chalk.grey(m))
3131
.replace(/<[^ ]+>/g, m => chalk.green(m))
3232
.replace(/ (-[-\w,]+)/g, m => chalk.bold(m))
33-
.replace(/`(.+)`/g, (_, m) => chalk.bold.cyan(m))
33+
.replace(/`([^`]+)`/g, (_, m) => chalk.bold.cyan(m))
3434
}
3535

3636
export function box(message, title, options) {

packages/cli/test/unit/dev.test.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@ describe('dev', () => {
5151
// Test error on second build so we cover oldInstance stuff
5252
const builder = new Builder()
5353
builder.nuxt = new Nuxt()
54-
Builder.prototype.build = jest.fn().mockImplementationOnce(() => Promise.reject(new Error('Build Error')))
54+
Builder.prototype.build = () => { throw new Error('Build Error') }
5555
await Nuxt.fileRestartHook(builder)
5656

5757
expect(Nuxt.prototype.close).toHaveBeenCalled()

packages/config/src/options.js

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -330,5 +330,10 @@ export function getNuxtConfig(_options) {
330330
bundleRenderer.runInNewContext = options.dev
331331
}
332332

333+
// Add loading screen
334+
if (options.dev) {
335+
options.devModules.push('@nuxt/loading-screen')
336+
}
337+
333338
return options
334339
}

packages/server/src/middleware/nuxt.js

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,13 @@ export default ({ options, nuxt, renderRoute, resources }) => async function nux
1212
const url = decodeURI(req.url)
1313
res.statusCode = 200
1414
const result = await renderRoute(url, context)
15+
16+
// If result is falsy, call renderLoading
17+
if (!result) {
18+
await nuxt.callHook('server:nuxt:renderLoading', req, res)
19+
return
20+
}
21+
1522
await nuxt.callHook('render:route', url, result, context)
1623
const {
1724
html,

packages/server/src/server.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -115,6 +115,7 @@ export default class Server {
115115
context: this.renderer.context
116116
}))
117117

118+
// Dev middleware
118119
if (this.options.dev) {
119120
this.useMiddleware((req, res, next) => {
120121
if (!this.devMiddleware) {

packages/vue-app/template/pages/index.vue

Lines changed: 9 additions & 77 deletions
Original file line numberDiff line numberDiff line change
@@ -2,15 +2,16 @@
22
<div>
33
<section class="Landscape">
44
<div class="Landscape__Logo">
5-
<div class="VueToNuxtLogo">
6-
<div class="Triangle Triangle--two"></div>
7-
<div class="Triangle Triangle--one"></div>
8-
<div class="Triangle Triangle--three"></div>
9-
<div class="Triangle Triangle--four"></div>
10-
</div>
11-
<h1 class="Landscape__Logo__Title">NUXT</h1>
5+
<svg class="logo" width="220" height="166" xmlns="http://www.w3.org/2000/svg">
6+
<g transform="translate(-18 -29)" fill="none" fill-rule="evenodd">
7+
<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" />
8+
<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" />
9+
<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" />
10+
<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" />
11+
</g>
12+
</svg>
1213
</div>
13-
<h2 class="Landscape__Title">The Vue Framework</h2>
14+
<h2 class="Landscape__Title">The Vue.js Framework</h2>
1415
<a href="https://nuxtjs.org/guide/installation#starting-from-scratch" target="_blank" class="button">
1516
Get Started
1617
</a>
@@ -85,75 +86,6 @@
8586
}
8687
}
8788
88-
.VueToNuxtLogo {
89-
display: inline-block;
90-
animation: turn 2s linear forwards;
91-
transform: rotateX(180deg);
92-
position: relative;
93-
overflow: hidden;
94-
height: 180px;
95-
width: 245px;
96-
}
97-
98-
.Triangle {
99-
position: absolute;
100-
top: 0;
101-
left: 0;
102-
width: 0;
103-
height: 0;
104-
}
105-
106-
.Triangle--one {
107-
border-left: 105px solid transparent;
108-
border-right: 105px solid transparent;
109-
border-bottom: 180px solid #41B883;
110-
}
111-
112-
.Triangle--two {
113-
top: 30px;
114-
left: 35px;
115-
animation: goright 0.5s linear forwards 2.5s;
116-
border-left: 87.5px solid transparent;
117-
border-right: 87.5px solid transparent;
118-
border-bottom: 150px solid #3B8070;
119-
}
120-
121-
.Triangle--three {
122-
top: 60px;
123-
left: 35px;
124-
animation: goright 0.5s linear forwards 2.5s;
125-
border-left: 70px solid transparent;
126-
border-right: 70px solid transparent;
127-
border-bottom: 120px solid #35495E;
128-
}
129-
130-
.Triangle--four {
131-
top: 120px;
132-
left: 70px;
133-
animation: godown 0.5s linear forwards 2s;
134-
border-left: 35px solid transparent;
135-
border-right: 35px solid transparent;
136-
border-bottom: 60px solid #fff;
137-
}
138-
139-
@keyframes turn {
140-
100% {
141-
transform: rotateX(0deg);
142-
}
143-
}
144-
145-
@keyframes godown {
146-
100% {
147-
top: 180px;
148-
}
149-
}
150-
151-
@keyframes goright {
152-
100% {
153-
left: 70px;
154-
}
155-
}
156-
15789
.button {
15890
font-family: "Quicksand", "Source Sans Pro", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
15991
position: relative;
Lines changed: 38 additions & 62 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
<style>
22
body, html, #<%= globals.id %> {
3-
background: <%= options.background %>;
3+
background: <%= (options.theme === 'dark' ? '#2F4A5F' : 'white') %>;
44
width: 100%;
55
height: 100%;
66
display: flex;
@@ -9,75 +9,51 @@
99
margin: 0;
1010
padding: 0;
1111
}
12-
13-
.logo {
14-
animation: turn 2s linear forwards 1s;
15-
transform: rotateX(180deg);
16-
position: relative;
17-
height: 346px;
18-
width: 536px;
19-
}
20-
21-
.triangle {
22-
position: absolute;
23-
top: 0;
24-
left: 0;
25-
width: 0;
26-
height: 0;
27-
}
28-
.triangle--one {
29-
border-left: 210px solid transparent;
30-
border-right: 210px solid transparent;
31-
border-bottom: 360px solid #41B883;
32-
}
33-
.triangle--two {
34-
top: 60px;
35-
left: 70px;
36-
animation: goright 0.5s linear forwards 3.5s;
37-
border-left: 175px solid transparent;
38-
border-right: 175px solid transparent;
39-
border-bottom: 300px solid #3B8070;
40-
}
41-
.triangle--three {
42-
top: 120px;
43-
left: 70px;
44-
animation: goright 0.5s linear forwards 3.5s;
45-
border-left: 140px solid transparent;
46-
border-right: 140px solid transparent;
47-
border-bottom: 240px solid #35495E;
12+
#nuxt-loading {
13+
animation: opacity 1s ease-in-out;
14+
animation-fill-mode: forwards;
15+
animation-delay: 1s;
16+
opacity: 0;
4817
}
49-
.triangle--four {
50-
top: 240px;
51-
left: 140px;
52-
animation: godown 0.5s linear forwards 3s;
53-
border-left: 70px solid transparent;
54-
border-right: 70px solid transparent;
55-
border-bottom: 120px solid #fff;
18+
#nuxt-loading .logo {
19+
position: relative;
20+
height: 166px;
21+
width: 220px;
5622
}
57-
58-
@keyframes turn {
59-
100% {
60-
transform: rotateX(0deg);
61-
}
23+
#nuxt-loading-status {
24+
font-family: sans-serif;
25+
font-weight: 500;
26+
text-align: center;
27+
color: <%= (options.theme === 'dark' ? 'white' : '#2F4A5F') %>;
6228
}
63-
@keyframes godown {
64-
100% {
65-
top: 360px;
66-
}
29+
#nuxt-loading-status.errored {
30+
color: <%= (options.theme === 'dark' ? '#da6371' : '#D0021B') %>;
6731
}
68-
@keyframes goright {
32+
@keyframes opacity {
6933
100% {
70-
left: 140px;
34+
opacity: 1;
7135
}
7236
}
7337
</style>
7438

75-
<div class="logo">
76-
<div class="triangle triangle--two"></div>
77-
<div class="triangle triangle--one"></div>
78-
<div class="triangle triangle--three"></div>
79-
<div class="triangle triangle--four"></div>
39+
<div id="nuxt-loading">
40+
<svg class="logo" width="220" height="166" xmlns="http://www.w3.org/2000/svg">
41+
<g transform="translate(-18 -29)" fill="none" fill-rule="evenodd">
42+
<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" />
43+
<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" />
44+
<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" />
45+
<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" />
46+
</g>
47+
</svg>
48+
<h3 id="nuxt-loading-status">Loading...</h3>
8049
</div>
8150

82-
83-
<!-- https://codepen.io/alexchopin/pen/jBWrej -->
51+
<script>
52+
window.addEventListener('error', function () {
53+
var e = document.getElementById('nuxt-loading-status');
54+
if (e) {
55+
e.innerHTML = 'An error occurred';
56+
e.className += 'errored'
57+
}
58+
});
59+
</script>

0 commit comments

Comments
 (0)