mirror of
https://github.com/nuxt/nuxt.git
synced 2024-11-27 08:02:01 +00:00
Merge branch 'dev' of github.com:Atinux/nuxt.js into dev
This commit is contained in:
commit
27b80739bc
@ -81,7 +81,12 @@ function genConfig (opts) {
|
||||
'external-helpers'
|
||||
],
|
||||
presets: [
|
||||
['es2015', { modules: false }]
|
||||
['env', {
|
||||
targets: {
|
||||
node: '6.11.0'
|
||||
},
|
||||
modules: false
|
||||
}]
|
||||
],
|
||||
'env': {
|
||||
'test': {
|
||||
|
@ -15,7 +15,8 @@ const packageJSON = readJSONSync(resolve(rootDir, 'package.json'))
|
||||
// Required and Excluded packages for start
|
||||
let requires = [
|
||||
'source-map-support',
|
||||
'pretty-error'
|
||||
'pretty-error',
|
||||
'minimist'
|
||||
]
|
||||
|
||||
const excludes = [
|
||||
|
@ -9,7 +9,7 @@ module.exports = {
|
||||
vendor: ['lodash'],
|
||||
extend (config, { dev }) {
|
||||
if (dev) {
|
||||
config.devtool = (dev ? 'eval-source-map' : false)
|
||||
config.devtool = 'eval-source-map'
|
||||
}
|
||||
const urlLoader = config.module.rules.find((loader) => loader.loader === 'url-loader')
|
||||
// Increase limit to 100KO
|
||||
|
@ -45,7 +45,7 @@ ul {
|
||||
list-style: none;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
with: 100%;
|
||||
width: 100%;
|
||||
max-width: 300px;
|
||||
margin: auto;
|
||||
}
|
||||
|
BIN
examples/global-css/assets/roboto.woff2
Normal file
BIN
examples/global-css/assets/roboto.woff2
Normal file
Binary file not shown.
@ -1,3 +1,11 @@
|
||||
@font-face {
|
||||
font-family: 'Roboto';
|
||||
font-style: normal;
|
||||
font-weight: 400;
|
||||
src: local('Roboto'), local('Roboto-Regular'), url(../assets/roboto.woff2) format('woff2');
|
||||
unicode-range: U+0460-052F, U+20B4, U+2DE0-2DFF, U+A640-A69F;
|
||||
}
|
||||
|
||||
body {
|
||||
background: #eee;
|
||||
text-align: center;
|
||||
@ -7,6 +15,7 @@ body {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
font-family: 'Roboto';
|
||||
}
|
||||
.content {
|
||||
margin-top: 100px;
|
||||
|
@ -9,5 +9,12 @@ module.exports = {
|
||||
css: [
|
||||
'bulma/css/bulma.css',
|
||||
'~/css/main.css'
|
||||
]
|
||||
],
|
||||
render: {
|
||||
bundleRenderer: {
|
||||
shouldPreload: (file, type) => {
|
||||
return ['script', 'style', 'font'].includes(type)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "nuxt-global-css",
|
||||
"dependencies": {
|
||||
"bulma": "^0.4.3",
|
||||
"bulma": "^0.5.1",
|
||||
"nuxt": "latest"
|
||||
},
|
||||
"scripts": {
|
||||
|
@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "nuxt-i18n",
|
||||
"dependencies": {
|
||||
"nuxt": "latest",
|
||||
"nuxt": "^1.0.0-rc9",
|
||||
"vue-i18n": "^7.0.5"
|
||||
},
|
||||
"scripts": {
|
||||
|
@ -3,7 +3,7 @@ import VueI18n from 'vue-i18n'
|
||||
|
||||
Vue.use(VueI18n)
|
||||
|
||||
export default ({ app, store }) => {
|
||||
export default ({ app, isClient, store }) => {
|
||||
// Set i18n instance on app
|
||||
// This way we can use it in middleware and pages asyncData/fetch
|
||||
app.i18n = new VueI18n({
|
||||
|
3
examples/layout-transitions/README.md
Normal file
3
examples/layout-transitions/README.md
Normal file
@ -0,0 +1,3 @@
|
||||
# Layout transitions with Nuxt.js
|
||||
|
||||
https://nuxtjs.org/examples/layout-transitions
|
52
examples/layout-transitions/assets/main.css
Normal file
52
examples/layout-transitions/assets/main.css
Normal file
@ -0,0 +1,52 @@
|
||||
body {
|
||||
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, 'Fira Sans', 'Droid Sans', 'Helvetica Neue', sans-serif;
|
||||
}
|
||||
|
||||
.container {
|
||||
text-align: center;
|
||||
padding-top: 200px;
|
||||
font-size: 20px;
|
||||
transition: all .5s cubic-bezier(.55,0,.1,1);
|
||||
}
|
||||
|
||||
.page-enter-active, .page-leave-active {
|
||||
transition: opacity .5s
|
||||
}
|
||||
.page-enter, .page-leave-active {
|
||||
opacity: 0
|
||||
}
|
||||
|
||||
.layout-enter-active, .layout-leave-active {
|
||||
transition: opacity .5s
|
||||
}
|
||||
.layout-enter, .layout-leave-active {
|
||||
opacity: 0
|
||||
}
|
||||
|
||||
.bounce-enter-active {
|
||||
animation: bounce-in .8s;
|
||||
}
|
||||
.bounce-leave-active {
|
||||
animation: bounce-out .5s;
|
||||
}
|
||||
@keyframes bounce-in {
|
||||
0% { transform: scale(0) }
|
||||
50% { transform: scale(1.5) }
|
||||
100% { transform: scale(1) }
|
||||
}
|
||||
@keyframes bounce-out {
|
||||
0% { transform: scale(1) }
|
||||
50% { transform: scale(1.5) }
|
||||
100% { transform: scale(0) }
|
||||
}
|
||||
|
||||
.slide-left-enter,
|
||||
.slide-right-leave-active {
|
||||
opacity: 0;
|
||||
transform: translate(30px, 0);
|
||||
}
|
||||
.slide-left-leave-active,
|
||||
.slide-right-enter {
|
||||
opacity: 0;
|
||||
transform: translate(-30px, 0);
|
||||
}
|
11
examples/layout-transitions/layouts/secondary.vue
Normal file
11
examples/layout-transitions/layouts/secondary.vue
Normal file
@ -0,0 +1,11 @@
|
||||
<template>
|
||||
<div>
|
||||
<menu>
|
||||
<ul>
|
||||
<li>Option 1</li>
|
||||
<li>Option 2</li>
|
||||
</ul>
|
||||
</menu>
|
||||
<nuxt/>
|
||||
</div>
|
||||
</template>
|
10
examples/layout-transitions/nuxt.config.js
Normal file
10
examples/layout-transitions/nuxt.config.js
Normal file
@ -0,0 +1,10 @@
|
||||
module.exports = {
|
||||
build: {
|
||||
vendor: ['axios']
|
||||
},
|
||||
css: ['~/assets/main.css'],
|
||||
layoutTransition: {
|
||||
name: 'layout',
|
||||
mode: 'out-in'
|
||||
}
|
||||
}
|
12
examples/layout-transitions/package.json
Normal file
12
examples/layout-transitions/package.json
Normal file
@ -0,0 +1,12 @@
|
||||
{
|
||||
"name": "nuxt-layout-transitions",
|
||||
"dependencies": {
|
||||
"axios": "^0.15.3",
|
||||
"nuxt": "latest"
|
||||
},
|
||||
"scripts": {
|
||||
"dev": "../../bin/nuxt",
|
||||
"build": "nuxt build",
|
||||
"start": "nuxt start"
|
||||
}
|
||||
}
|
13
examples/layout-transitions/pages/about.vue
Normal file
13
examples/layout-transitions/pages/about.vue
Normal file
@ -0,0 +1,13 @@
|
||||
<template>
|
||||
<div class="container">
|
||||
<h1>About page</h1>
|
||||
<nuxt-link to="/">Home page</nuxt-link>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
layout: 'secondary',
|
||||
transition: 'bounce'
|
||||
}
|
||||
</script>
|
7
examples/layout-transitions/pages/index.vue
Normal file
7
examples/layout-transitions/pages/index.vue
Normal file
@ -0,0 +1,7 @@
|
||||
<template>
|
||||
<div class="container">
|
||||
<h1>Home page</h1>
|
||||
<p><nuxt-link to="/about">About page</nuxt-link></p>
|
||||
<p><nuxt-link to="/users">Lists of users</nuxt-link></p>
|
||||
</div>
|
||||
</template>
|
71
examples/layout-transitions/pages/users.vue
Normal file
71
examples/layout-transitions/pages/users.vue
Normal file
@ -0,0 +1,71 @@
|
||||
<template>
|
||||
<div class="container">
|
||||
<nuxt-link v-if="page > 1" :to="'?page=' + (page - 1)">< Prev</nuxt-link>
|
||||
<a v-else class="disabled">< Prev</a>
|
||||
<span>{{ page }}/{{ totalPages }}</span>
|
||||
<nuxt-link v-if="page < totalPages" :to="'?page=' + (page + 1)">Next ></nuxt-link>
|
||||
<a v-else class="disabled">Next ></a>
|
||||
<ul>
|
||||
<li v-for="user in users">
|
||||
<img :src="user.avatar" class="avatar" />
|
||||
<span>{{ user.first_name }} {{ user.last_name }}</span>
|
||||
</li>
|
||||
</ul>
|
||||
<p><nuxt-link to="/">Back home</nuxt-link></p>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import axios from 'axios'
|
||||
|
||||
export default {
|
||||
transition (to, from) {
|
||||
if (!from) return 'slide-left'
|
||||
return +to.query.page < +from.query.page ? 'slide-right' : 'slide-left'
|
||||
},
|
||||
async asyncData ({ query }) {
|
||||
const page = query.page || 1
|
||||
const { data } = await axios.get(`https://reqres.in/api/users?page=${page}`)
|
||||
return {
|
||||
page: +data.page,
|
||||
totalPages: data.total_pages,
|
||||
users: data.data
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
a {
|
||||
display: inline-block;
|
||||
margin: 0 1em;
|
||||
color: #34495e;
|
||||
text-decoration: none;
|
||||
}
|
||||
a.disabled {
|
||||
color: #ccc;
|
||||
}
|
||||
ul {
|
||||
margin: auto;
|
||||
padding: 0;
|
||||
width: 100%;
|
||||
max-width: 400px;
|
||||
padding-top: 40px;
|
||||
}
|
||||
li {
|
||||
list-style-type: none;
|
||||
width: 400px;
|
||||
border: 1px #ddd solid;
|
||||
overflow: hidden;
|
||||
}
|
||||
li img {
|
||||
float: left;
|
||||
width: 100px;
|
||||
height: 100px;
|
||||
}
|
||||
li span {
|
||||
display: inline-block;
|
||||
padding-top: 40px;
|
||||
text-transform: uppercase;
|
||||
}
|
||||
</style>
|
@ -23,23 +23,19 @@ module.exports = {
|
||||
*/
|
||||
css: ['~/assets/main.css'],
|
||||
/*
|
||||
** Cutomize loading indicator
|
||||
** Customize loading indicator
|
||||
*/
|
||||
loadingIndicator: {
|
||||
/*
|
||||
** See https://github.com/nuxt/nuxt.js/tree/dev/lib/app/views/loading for available loading indicators
|
||||
** You can add a custom indicator by giving a path
|
||||
** Default: 'circle'
|
||||
*/
|
||||
name: 'folding-cube',
|
||||
// name: 'folding-cube',
|
||||
/*
|
||||
** You can give custom options given to the template
|
||||
** See https://github.com/nuxt/nuxt.js/blob/dev/lib/app/views/loading/folding-cube.html
|
||||
** Default:
|
||||
** - color: '#3B8070'
|
||||
** - background: 'white'
|
||||
*/
|
||||
color: '#222',
|
||||
background: 'white'
|
||||
// color: '#DBE1EC'
|
||||
// background: 'white'
|
||||
}
|
||||
}
|
||||
|
@ -7,7 +7,7 @@ module.exports = function (options) {
|
||||
loader: 'ts-loader'
|
||||
})
|
||||
// Add TypeScript loader for vue files
|
||||
for (rule of config.module.rules) {
|
||||
for (let rule of config.module.rules) {
|
||||
if (rule.loader === 'vue-loader') {
|
||||
rule.query.loaders.ts = 'ts-loader?{"appendTsSuffixTo":["\\\\.vue$"]}'
|
||||
}
|
||||
|
@ -1,8 +1,8 @@
|
||||
{
|
||||
"name": "nuxt-vue-apollo",
|
||||
"dependencies": {
|
||||
"@nuxtjs/apollo": "^2.0.0",
|
||||
"nuxt": "^1.0.0-rc6"
|
||||
"@nuxtjs/apollo": "^2.1.1",
|
||||
"nuxt": "^1.0.0-rc9"
|
||||
},
|
||||
"scripts": {
|
||||
"dev": "nuxt",
|
||||
|
@ -1,7 +1,9 @@
|
||||
<template>
|
||||
<div id="__nuxt">
|
||||
<% if (loading) { %><nuxt-loading ref="loading"></nuxt-loading><% } %>
|
||||
<component v-if="layout" :is="nuxt.err ? 'nuxt' : layout"></component>
|
||||
<% if (layoutTransition) { %><transition name="<%= layoutTransition.name %>" mode="<%= layoutTransition.mode %>"><% } %>
|
||||
<component v-if="layout" :is="nuxt.err ? 'nuxt' : layout" :key="layoutName"></component>
|
||||
<% if (layoutTransition) { %></transition><% } %>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
|
@ -26,18 +26,19 @@ let router
|
||||
|
||||
// Try to rehydrate SSR data from window
|
||||
const NUXT = window.__NUXT__ || {}
|
||||
NUXT.components = window.__COMPONENTS__ || null
|
||||
|
||||
<% if (debug || mode === 'spa') { %>
|
||||
// Setup global Vue error handler
|
||||
const defaultErrorHandler = Vue.config.errorHandler
|
||||
Vue.config.errorHandler = function (err, vm, info) {
|
||||
err.statusCode = err.statusCode || err.name || 'Whoops!'
|
||||
err.message = err.message || err.toString()
|
||||
const nuxtError = {
|
||||
statusCode: err.statusCode || err.name || 'Whoops!',
|
||||
message: err.message || err.toString()
|
||||
}
|
||||
|
||||
// Show Nuxt Error Page
|
||||
if(vm && vm.$root && vm.$root.$nuxt && vm.$root.$nuxt.error && info !== 'render function') {
|
||||
vm.$root.$nuxt.error(err)
|
||||
vm.$root.$nuxt.error(nuxtError)
|
||||
}
|
||||
|
||||
// Call other handler if exist
|
||||
@ -49,7 +50,7 @@ Vue.config.errorHandler = function (err, vm, info) {
|
||||
if (process.env.NODE_ENV !== 'production') {
|
||||
console.error(err)
|
||||
} else {
|
||||
console.error(err.message)
|
||||
console.error(err.message || nuxtError.message)
|
||||
}
|
||||
}
|
||||
<% } %>
|
||||
@ -132,28 +133,29 @@ async function loadAsyncComponents (to, from, next) {
|
||||
}
|
||||
}
|
||||
|
||||
function applySSRData(Component, ssrData) {
|
||||
if (NUXT.serverRendered && ssrData) {
|
||||
applyAsyncData(Component, ssrData)
|
||||
}
|
||||
Component._Ctor = Component
|
||||
return Component
|
||||
}
|
||||
|
||||
// Get matched components
|
||||
function resolveComponents(router) {
|
||||
const path = getLocation(router.options.base)
|
||||
const path = getLocation(router.options.base, router.options.mode)
|
||||
|
||||
return flatMapComponents(router.match(path), (Component, _, match, key, index) => {
|
||||
// If component already resolved
|
||||
if (typeof Component !== 'function' || Component.options) {
|
||||
const _Component = sanitizeComponent(Component)
|
||||
const _Component = applySSRData(sanitizeComponent(Component), NUXT.data ? NUXT.data[index] : null)
|
||||
match.components[key] = _Component
|
||||
return _Component
|
||||
}
|
||||
|
||||
// Resolve component
|
||||
return Component().then(Component => {
|
||||
const _Component = sanitizeComponent(Component)
|
||||
if (NUXT.serverRendered) {
|
||||
applyAsyncData(_Component, NUXT.data[index])
|
||||
if (NUXT.components) {
|
||||
Component.options.components = Object.assign(_Component.options.components, NUXT.components[index])
|
||||
}
|
||||
_Component._Ctor = _Component
|
||||
}
|
||||
const _Component = applySSRData(sanitizeComponent(Component), NUXT.data ? NUXT.data[index] : null)
|
||||
match.components[key] = _Component
|
||||
return _Component
|
||||
})
|
||||
@ -228,7 +230,7 @@ async function render (to, from, next) {
|
||||
await callMiddleware.call(this, Components, context, layout)
|
||||
if (context._redirected) return
|
||||
|
||||
this.error({ statusCode: 404, message: 'This page could not be found.' })
|
||||
this.error({ statusCode: 404, message: '<%= messages.error_404 %>' })
|
||||
return next()
|
||||
}
|
||||
|
||||
@ -272,7 +274,7 @@ async function render (to, from, next) {
|
||||
})
|
||||
// ...If .validate() returned false
|
||||
if (!isValid) {
|
||||
this.error({ statusCode: 404, message: 'This page could not be found.' })
|
||||
this.error({ statusCode: 404, message: '<%= messages.error_404 %>' })
|
||||
return next()
|
||||
}
|
||||
|
||||
|
@ -37,6 +37,19 @@ export default {
|
||||
name: 'nuxt-child',
|
||||
functional: true,
|
||||
render (h, { parent, data }) {
|
||||
const nuxt = parent.$root.nuxt
|
||||
const component = parent.$route.matched[0].components.default
|
||||
|
||||
const layoutUid = parent._uid
|
||||
const layoutName = component.options ? component.options.layout : null
|
||||
|
||||
// If we're changing layout render the stored vnode
|
||||
if (nuxt._layoutUid === layoutUid &&
|
||||
nuxt._layoutName !== layoutName) return nuxt._childVnode
|
||||
|
||||
nuxt._layoutUid = layoutUid
|
||||
nuxt._layoutName = layoutName
|
||||
|
||||
data.nuxtChild = true
|
||||
const _parent = parent
|
||||
const transitions = parent.$nuxt.nuxt.transitions
|
||||
@ -62,11 +75,14 @@ export default {
|
||||
listeners[key] = transition[key].bind(_parent)
|
||||
}
|
||||
})
|
||||
return h('transition', {
|
||||
|
||||
nuxt._childVnode = h('transition', {
|
||||
props: transitionProps,
|
||||
on: listeners
|
||||
}, [
|
||||
h('router-view', data)
|
||||
])
|
||||
|
||||
return nuxt._childVnode
|
||||
}
|
||||
}
|
||||
|
@ -1,32 +1,21 @@
|
||||
<template>
|
||||
<div class="__nuxt-error-page">
|
||||
<div class="container">
|
||||
<div class="__nuxt-error-page">
|
||||
<div class="error">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="90" height="90" fill="#DBE1EC" viewBox="0 0 48 48"><path d="M22 30h4v4h-4zm0-16h4v12h-4zm1.99-10C12.94 4 4 12.95 4 24s8.94 20 19.99 20S44 35.05 44 24 35.04 4 23.99 4zM24 40c-8.84 0-16-7.16-16-16S15.16 8 24 8s16 7.16 16 16-7.16 16-16 16z"/></svg>
|
||||
|
||||
<div class="row">
|
||||
<div class="column">
|
||||
<h1>{{ statusCode }} </h1>
|
||||
<h3> {{ message }} </h3>
|
||||
<p v-if="statusCode === 404">
|
||||
<nuxt-link class="error-link" to="/">Back to the home page</nuxt-link>
|
||||
<div class="title">{{ message }}</div>
|
||||
<p class="description" v-if="statusCode === 404">
|
||||
<nuxt-link class="error-link" to="/"><%= messages.back_to_home %></nuxt-link>
|
||||
</p>
|
||||
<% if(debug) { %>
|
||||
<small v-else>
|
||||
Open developer tools to view stack trace
|
||||
</small>
|
||||
<p class="description" v-else><%= messages.client_error_details %></p>
|
||||
<% } %>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
<div class="column">
|
||||
<div class="poweredby">
|
||||
<small> Powered by <a href="https://nuxtjs.org" target="_blank" rel="noopener">Nuxt.js</a> </small>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
<div class="logo">
|
||||
<a href="https://nuxtjs.org" target="_blank" rel="noopener"><%= messages.nuxtjs %></a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
@ -35,14 +24,17 @@ export default {
|
||||
props: ['error'],
|
||||
head () {
|
||||
return {
|
||||
title: this.statusCode + ' - ' + this.message,
|
||||
link: [
|
||||
{ rel: 'stylesheet', href: 'https://cdnjs.cloudflare.com/ajax/libs/normalize/7.0.0/normalize.min.css', type: 'text/css', media: 'all' },
|
||||
{ rel: 'stylesheet', href: 'https://cdnjs.cloudflare.com/ajax/libs/milligram/1.3.0/milligram.min.css', type: 'text/css', media: 'all' }
|
||||
title: this.message,
|
||||
meta: [
|
||||
{
|
||||
name: 'viewport',
|
||||
content: 'width=device-width,initial-scale=1.0,minimum-scale=1.0,maximum-scale=1.0,user-scalable=no'
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
<% if(debug) { %>
|
||||
// Only on debug mode
|
||||
data () {
|
||||
return {
|
||||
mounted: false
|
||||
@ -51,13 +43,23 @@ export default {
|
||||
mounted () {
|
||||
this.mounted = true
|
||||
},
|
||||
created () {
|
||||
console.error(this.error)
|
||||
},
|
||||
watch: {
|
||||
error(newErr) {
|
||||
if(newErr) {
|
||||
console.error(newErr)
|
||||
}
|
||||
}
|
||||
},
|
||||
<% } %>
|
||||
computed: {
|
||||
statusCode () {
|
||||
return (this.error && this.error.statusCode) || 500
|
||||
},
|
||||
message () {
|
||||
return this.error.message || 'Nuxt Server Error'
|
||||
return this.error.message || '<%= messages.client_error %>'
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -65,29 +67,46 @@ export default {
|
||||
|
||||
<style>
|
||||
.__nuxt-error-page {
|
||||
background: #F5F7FA;
|
||||
font-size: 14px;
|
||||
word-spacing: 1px;
|
||||
-ms-text-size-adjust: 100%;
|
||||
-webkit-text-size-adjust: 100%;
|
||||
-moz-osx-font-smoothing: grayscale;
|
||||
-webkit-font-smoothing: antialiased;
|
||||
padding: 1rem;
|
||||
background: #F7F8FB;
|
||||
color: #47494E;
|
||||
text-align: center;
|
||||
}
|
||||
.__nuxt-error-page .container {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
flex-direction: column;
|
||||
height: 100vh;
|
||||
margin: 0 auto;
|
||||
max-width: 70%;
|
||||
font-family: sans-serif;
|
||||
font-weight: 100 !important;
|
||||
-ms-text-size-adjust: 100%;
|
||||
-webkit-text-size-adjust: 100%;
|
||||
-webkit-font-smoothing: antialiased;
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
}
|
||||
.__nuxt-error-page .poweredby {
|
||||
text-align: center;
|
||||
margin-top: 10%;
|
||||
.__nuxt-error-page .error {
|
||||
max-width: 450px;
|
||||
}
|
||||
.__nuxt-error-page .title {
|
||||
font-size: 1.5rem;
|
||||
margin-top: 15px;
|
||||
color: #47494E;
|
||||
margin-bottom: 8px;
|
||||
}
|
||||
.__nuxt-error-page .description {
|
||||
color: #7F828B;
|
||||
line-height: 21px;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
.__nuxt-error-page a {
|
||||
color: #42b983 !important;
|
||||
color: #7F828B !important;
|
||||
text-decoration: none;
|
||||
}
|
||||
.__nuxt-error-page .logo {
|
||||
position: fixed;
|
||||
left: 12px;
|
||||
bottom: 12px;
|
||||
}
|
||||
</style>
|
||||
|
@ -1,6 +1,8 @@
|
||||
<template>
|
||||
<div class="nuxt">
|
||||
<nuxt-error v-if="nuxt.err" :error="nuxt.err"></nuxt-error>
|
||||
<nuxt-child :key="routerViewKey" v-else></nuxt-child>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
|
@ -43,7 +43,11 @@ const defaultTransition = <%=
|
||||
async function createApp (ssrContext) {
|
||||
const router = createRouter()
|
||||
|
||||
<% if (store) { %>const store = createStore()<% } %>
|
||||
<% if (store) { %>
|
||||
const store = createStore()
|
||||
// Add this.$router into store actions/mutations
|
||||
store.$router = router
|
||||
<% } %>
|
||||
|
||||
// Create Root instance
|
||||
// here we inject the router and store to all child components,
|
||||
@ -135,6 +139,15 @@ async function createApp (ssrContext) {
|
||||
<% } %>
|
||||
}
|
||||
|
||||
<% if (store) { %>
|
||||
if (process.browser) {
|
||||
// Replace store state before plugins execution
|
||||
if (window.__NUXT__ && window.__NUXT__.state) {
|
||||
store.replaceState(window.__NUXT__.state)
|
||||
}
|
||||
}
|
||||
<% } %>
|
||||
|
||||
<% plugins.filter(p => p.ssr).forEach(plugin => { %>
|
||||
if (typeof <%= plugin.name %> === 'function') await <%= plugin.name %>(ctx, inject)<% }) %>
|
||||
<% if (plugins.filter(p => !p.ssr).length) { %>
|
||||
@ -142,14 +155,8 @@ async function createApp (ssrContext) {
|
||||
if (typeof <%= plugin.name %> === 'function') await <%= plugin.name %>(ctx, inject)<% }) %>
|
||||
}<% } %>
|
||||
|
||||
<% if (store) { %>
|
||||
if (process.browser) {
|
||||
// Replace store state before calling plugins
|
||||
if (window.__NUXT__ && window.__NUXT__.state) {
|
||||
store.replaceState(window.__NUXT__.state)
|
||||
}
|
||||
}
|
||||
<% } %>
|
||||
// Inject context
|
||||
inject('ctx', ctx)
|
||||
|
||||
if (process.server && ssrContext && ssrContext.url) {
|
||||
await new Promise((resolve, reject) => {
|
||||
|
@ -193,7 +193,7 @@ export default async context => {
|
||||
|
||||
// If no Components found, returns 404
|
||||
if (!Components.length) {
|
||||
context.nuxt.error = context.error({ statusCode: 404, message: 'This page could not be found.' })
|
||||
context.nuxt.error = context.error({ statusCode: 404, message: '<%= messages.error_404 %>' })
|
||||
}
|
||||
|
||||
<% if (isDev) { %>if (asyncDatas.length) debug('Data fetching ' + context.url + ': ' + (Date.now() - s) + 'ms')<% } %>
|
||||
|
@ -108,6 +108,9 @@ export function getContext (context, app) {
|
||||
if (ctx.isServer && context.beforeRenderFns) {
|
||||
ctx.beforeNuxtRender = (fn) => context.beforeRenderFns.push(fn)
|
||||
}
|
||||
if (ctx.isClient && window.__NUXT__) {
|
||||
ctx.nuxtState = window.__NUXT__
|
||||
}
|
||||
return ctx
|
||||
}
|
||||
|
||||
@ -144,8 +147,11 @@ export function promisify (fn, context) {
|
||||
}
|
||||
|
||||
// Imported from vue-router
|
||||
export function getLocation (base) {
|
||||
export function getLocation (base, mode) {
|
||||
var path = window.location.pathname
|
||||
if (mode === 'hash') {
|
||||
return window.location.hash.replace(/^#\//, '')
|
||||
}
|
||||
if (base && path.indexOf(base) === 0) {
|
||||
path = path.slice(base.length)
|
||||
}
|
||||
|
File diff suppressed because one or more lines are too long
@ -203,6 +203,7 @@ export default class Builder extends Tapable {
|
||||
]
|
||||
const templateVars = {
|
||||
options: this.options,
|
||||
messages: this.options.messages,
|
||||
uniqBy: _.uniqBy,
|
||||
isDev: this.options.dev,
|
||||
debug: this.options.debug,
|
||||
@ -218,6 +219,7 @@ export default class Builder extends Tapable {
|
||||
layouts: Object.assign({}, this.options.layouts),
|
||||
loading: typeof this.options.loading === 'string' ? this.relativeToBuild(this.options.srcDir, this.options.loading) : this.options.loading,
|
||||
transition: this.options.transition,
|
||||
layoutTransition: this.options.layoutTransition,
|
||||
components: {
|
||||
ErrorPage: this.options.ErrorPage ? this.relativeToBuild(this.options.ErrorPage) : null
|
||||
}
|
||||
@ -485,9 +487,9 @@ export default class Builder extends Tapable {
|
||||
compiler.run((err, stats) => {
|
||||
/* istanbul ignore if */
|
||||
if (err) {
|
||||
console.error(err) // eslint-disable-line no-console
|
||||
return reject(err)
|
||||
}
|
||||
if (err) return console.error(err) // eslint-disable-line no-console
|
||||
|
||||
// Show build stats for production
|
||||
console.log(stats.toString(this.webpackStats)) // eslint-disable-line no-console
|
||||
@ -518,7 +520,7 @@ export default class Builder extends Tapable {
|
||||
|
||||
this.webpackHotMiddleware = pify(webpackHotMiddleware(this.compiler.client, Object.assign({
|
||||
log: false,
|
||||
heartbeat: 1000
|
||||
heartbeat: 10000
|
||||
}, this.options.build.hotMiddleware)))
|
||||
|
||||
// Inject to renderer instance
|
||||
|
@ -5,7 +5,6 @@ import HTMLPlugin from 'html-webpack-plugin'
|
||||
import FriendlyErrorsWebpackPlugin from 'friendly-errors-webpack-plugin'
|
||||
import ProgressBarPlugin from 'progress-bar-webpack-plugin'
|
||||
import { BundleAnalyzerPlugin } from 'webpack-bundle-analyzer'
|
||||
// import MinifyPlugin from 'babel-minify-webpack-plugin'
|
||||
import { resolve } from 'path'
|
||||
import { existsSync } from 'fs'
|
||||
import Debug from 'debug'
|
||||
@ -77,7 +76,7 @@ export default function webpackClientConfig () {
|
||||
// Env object defined in nuxt.config.js
|
||||
let env = {}
|
||||
each(this.options.env, (value, key) => {
|
||||
env['process.env.' + key] = (typeof value === 'string' ? JSON.stringify(value) : value)
|
||||
env['process.env.' + key] = (['boolean', 'number'].indexOf(typeof value) !== -1 ? value : JSON.stringify(value))
|
||||
})
|
||||
|
||||
// Webpack common plugins
|
||||
@ -153,7 +152,7 @@ export default function webpackClientConfig () {
|
||||
// Add HMR support
|
||||
config.entry.app = [
|
||||
// https://github.com/glenjamin/webpack-hot-middleware#config
|
||||
`webpack-hot-middleware/client?name=client&reload=true&timeout=3000&path=${this.options.router.base}/__webpack_hmr`.replace(/\/\//g, '/'),
|
||||
`webpack-hot-middleware/client?name=client&reload=true&timeout=30000&path=${this.options.router.base}/__webpack_hmr`.replace(/\/\//g, '/'),
|
||||
config.entry.app
|
||||
]
|
||||
config.plugins.push(
|
||||
@ -191,17 +190,13 @@ export default function webpackClientConfig () {
|
||||
if (!this.options.dev) {
|
||||
// Scope Hoisting
|
||||
config.plugins.push(
|
||||
new webpack.optimize.ModuleConcatenationPlugin()
|
||||
// new webpack.optimize.ModuleConcatenationPlugin()
|
||||
)
|
||||
|
||||
// https://webpack.js.org/plugins/hashed-module-ids-plugin
|
||||
config.plugins.push(new webpack.HashedModuleIdsPlugin())
|
||||
|
||||
// Minify JS
|
||||
|
||||
// https://github.com/webpack-contrib/babel-minify-webpack-plugin
|
||||
// config.plugins.push(new MinifyPlugin())
|
||||
|
||||
// https://github.com/webpack-contrib/uglifyjs-webpack-plugin
|
||||
config.plugins.push(
|
||||
new webpack.optimize.UglifyJsPlugin({
|
||||
|
@ -17,7 +17,7 @@ export default function webpackServerConfig () {
|
||||
// env object defined in nuxt.config.js
|
||||
let env = {}
|
||||
each(this.options.env, (value, key) => {
|
||||
env['process.env.' + key] = (typeof value === 'string' ? JSON.stringify(value) : value)
|
||||
env['process.env.' + key] = (['boolean', 'number'].indexOf(typeof value) !== -1 ? value : JSON.stringify(value))
|
||||
})
|
||||
|
||||
config = Object.assign(config, {
|
||||
|
@ -24,6 +24,9 @@ Options.from = function (_options) {
|
||||
if (typeof options.transition === 'string') {
|
||||
options.transition = { name: options.transition }
|
||||
}
|
||||
if (typeof options.layoutTransition === 'string') {
|
||||
options.layoutTransition = { name: options.layoutTransition }
|
||||
}
|
||||
|
||||
// Apply defaults
|
||||
_.defaultsDeep(options, Options.defaults)
|
||||
@ -60,8 +63,8 @@ Options.from = function (_options) {
|
||||
|
||||
// Apply defaults to loadingIndicator
|
||||
options.loadingIndicator = Object.assign({
|
||||
name: 'circle',
|
||||
color: '#3B8070',
|
||||
name: 'pulse',
|
||||
color: '#dbe1ec',
|
||||
background: 'white'
|
||||
}, options.loadingIndicator)
|
||||
|
||||
@ -243,6 +246,10 @@ Options.defaults = {
|
||||
appearActiveClass: 'appear-active',
|
||||
appearToClass: 'appear-to'
|
||||
},
|
||||
layoutTransition: {
|
||||
name: 'layout',
|
||||
mode: 'out-in'
|
||||
},
|
||||
router: {
|
||||
mode: 'history',
|
||||
base: '/',
|
||||
@ -274,5 +281,17 @@ Options.defaults = {
|
||||
ignored: /-dll/
|
||||
},
|
||||
chokidar: {}
|
||||
},
|
||||
editor: {
|
||||
editor: 'code'
|
||||
},
|
||||
messages: {
|
||||
error_404: 'This page could not be found',
|
||||
server_error: 'Server error',
|
||||
nuxtjs: 'Nuxt.js',
|
||||
back_to_home: 'Back to the home page',
|
||||
server_error_details: 'An error occurred in the application and your page could not be served. If you are the application owner, check your logs for details.',
|
||||
client_error: 'Error',
|
||||
client_error_details: 'An error occurred while rendering the page. Check developer tools console for details.'
|
||||
}
|
||||
}
|
||||
|
@ -50,23 +50,28 @@ export default class MetaRenderer {
|
||||
// Get vue-meta context
|
||||
const m = await this.getMeta(url)
|
||||
// HTML_ATTRS
|
||||
meta.HTML_ATTRS = 'data-n-head-ssr ' + m.htmlAttrs.text()
|
||||
meta.HTML_ATTRS = m.htmlAttrs.text()
|
||||
// BODY_ATTRS
|
||||
meta.BODY_ATTRS = m.bodyAttrs.text()
|
||||
// HEAD tags
|
||||
meta.HEAD = m.meta.text() + m.title.text() + m.link.text() + m.style.text() + m.script.text() + m.noscript.text()
|
||||
// Resources Hints
|
||||
meta.resourceHints = ''
|
||||
// Resource Hints
|
||||
const clientManifest = this.renderer.resources.clientManifest
|
||||
if (this.options.render.resourceHints && clientManifest) {
|
||||
const publicPath = clientManifest.publicPath || '/_nuxt/'
|
||||
// Pre-Load initial resources
|
||||
if (Array.isArray(clientManifest.initial)) {
|
||||
meta.HEAD += clientManifest.initial.map(r => `<link rel="preload" href="${publicPath}${r}" as="script" />`).join('')
|
||||
meta.resourceHints += clientManifest.initial.map(r => `<link rel="preload" href="${publicPath}${r}" as="script" />`).join('')
|
||||
}
|
||||
|
||||
// Pre-Fetch async resources
|
||||
if (Array.isArray(clientManifest.async)) {
|
||||
meta.HEAD += clientManifest.async.map(r => `<link rel="prefetch" href="${publicPath}${r}" />`).join('')
|
||||
meta.resourceHints += clientManifest.async.map(r => `<link rel="prefetch" href="${publicPath}${r}" />`).join('')
|
||||
}
|
||||
// Add them to HEAD
|
||||
if (meta.resourceHints) {
|
||||
meta.HEAD += meta.resourceHints
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -108,6 +108,9 @@ export default class Renderer extends Tapable {
|
||||
this.resources.loadingHTML = ''
|
||||
}
|
||||
|
||||
// Call resourcesLoaded plugin
|
||||
await this.applyPluginsAsync('resourcesLoaded', this.resources)
|
||||
|
||||
if (updated.length > 0) {
|
||||
// debug('Updated', updated.join(', '), isServer)
|
||||
this.createRenderer()
|
||||
@ -183,7 +186,7 @@ export default class Renderer extends Tapable {
|
||||
}
|
||||
|
||||
const handler = m.handler || m
|
||||
const path = (this.options.router.base + (m.path ? m.path : '')).replace(/\/\//g, '/')
|
||||
const path = (((m.prefix !== false) ? this.options.router.base : '') + (m.path ? m.path : '')).replace(/\/\//g, '/')
|
||||
|
||||
// Inject $src and $m to final handler
|
||||
if (src) handler.$src = src
|
||||
@ -193,6 +196,10 @@ export default class Renderer extends Tapable {
|
||||
this.app.use(path, handler)
|
||||
}
|
||||
|
||||
get publicPath () {
|
||||
return isUrl(this.options.build.publicPath) ? Options.defaults.build.publicPath : this.options.build.publicPath
|
||||
}
|
||||
|
||||
async setupMiddleware () {
|
||||
// Apply setupMiddleware from modules first
|
||||
await this.applyPluginsAsync('setupMiddleware', this.app)
|
||||
@ -225,6 +232,32 @@ export default class Renderer extends Tapable {
|
||||
})
|
||||
}
|
||||
|
||||
// open in editor for debug mode only
|
||||
const _this = this
|
||||
if (this.options.debug) {
|
||||
this.useMiddleware({
|
||||
path: '_open',
|
||||
handler (req, res) {
|
||||
// Lazy load open-in-editor
|
||||
const openInEditor = require('open-in-editor')
|
||||
const editor = openInEditor.configure(_this.options.editor)
|
||||
// Parse Query
|
||||
const query = req.url.split('?')[1].split('&').reduce((q, part) => {
|
||||
const s = part.split('=')
|
||||
q[s[0]] = decodeURIComponent(s[1])
|
||||
return q
|
||||
}, {})
|
||||
// eslint-disable-next-line no-console
|
||||
console.log('[open in editor]', query.file)
|
||||
editor.open(query.file).then(() => {
|
||||
res.end('opened in editor!')
|
||||
}).catch(err => {
|
||||
res.end(err)
|
||||
})
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
// For serving static/ files to /
|
||||
this.useMiddleware(serveStatic(resolve(this.options.srcDir, 'static'), this.options.render.static))
|
||||
|
||||
@ -233,10 +266,10 @@ export default class Renderer extends Tapable {
|
||||
if (!this.options.dev) {
|
||||
const distDir = resolve(this.options.buildDir, 'dist')
|
||||
this.useMiddleware({
|
||||
path: isUrl(this.options.build.publicPath) ? Options.defaults.build.publicPath : this.options.build.publicPath,
|
||||
path: this.publicPath,
|
||||
handler: serveStatic(distDir, {
|
||||
index: false, // Don't serve index.html template
|
||||
maxAge: (this.options.dev ? 0 : '1y') // 1 year in production
|
||||
maxAge: '1y' // 1 year in production
|
||||
})
|
||||
})
|
||||
}
|
||||
@ -319,6 +352,11 @@ export default class Renderer extends Tapable {
|
||||
err.message = err.message || 'Nuxt Server Error'
|
||||
err.name = (!err.name || err.name === 'Error') ? 'NuxtServerError' : err.name
|
||||
|
||||
// We hide actual errors from end users, so show them on server logs
|
||||
if (err.statusCode !== 404) {
|
||||
console.error(err) // eslint-disable-line no-console
|
||||
}
|
||||
|
||||
const sendResponse = (content, type = 'text/html') => {
|
||||
// Set Headers
|
||||
res.statusCode = err.statusCode
|
||||
@ -398,7 +436,6 @@ export default class Renderer extends Tapable {
|
||||
const contents = smc.sourceContentFor(source)
|
||||
if (contents) {
|
||||
frame.contents = contents
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -424,12 +461,15 @@ export default class Renderer extends Tapable {
|
||||
this.options.buildDir
|
||||
]
|
||||
|
||||
// Scan filesystem
|
||||
// Scan filesystem for real path
|
||||
for (let pathDir of searchPath) {
|
||||
let fullPath = resolve(pathDir, frame.fileName)
|
||||
let source = await fs.readFile(fullPath, 'utf-8').catch(() => null)
|
||||
if (source) {
|
||||
if (!frame.contents) {
|
||||
frame.contents = source
|
||||
}
|
||||
frame.fullPath = fullPath
|
||||
return
|
||||
}
|
||||
}
|
||||
@ -453,9 +493,15 @@ export default class Renderer extends Tapable {
|
||||
// Basic response if SSR is disabled or spa data provided
|
||||
const spa = context.spa || (context.res && context.res.spa)
|
||||
if (this.noSSR || spa) {
|
||||
const { HTML_ATTRS, BODY_ATTRS, HEAD } = await this.metaRenderer.render(context)
|
||||
const { HTML_ATTRS, BODY_ATTRS, HEAD, resourceHints } = await this.metaRenderer.render(context)
|
||||
const APP = `<div id="__nuxt">${this.resources.loadingHTML}</div>`
|
||||
|
||||
// Detect 404 errors
|
||||
if (url.includes(this.options.build.publicPath) || url.includes('__webpack')) {
|
||||
const err = { statusCode: 404, message: this.options.messages.error_404, name: 'ResourceNotFound' }
|
||||
throw err
|
||||
}
|
||||
|
||||
const data = {
|
||||
HTML_ATTRS,
|
||||
BODY_ATTRS,
|
||||
@ -465,7 +511,7 @@ export default class Renderer extends Tapable {
|
||||
|
||||
const html = this.resources.spaTemplate(data)
|
||||
|
||||
return { html }
|
||||
return { html, resourceHints }
|
||||
}
|
||||
|
||||
// Call renderToString from the bundleRenderer and generate the HTML (will update the context as well)
|
||||
|
18
package.json
18
package.json
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "nuxt",
|
||||
"version": "1.0.0-rc7",
|
||||
"version": "1.0.0-rc11",
|
||||
"description": "A minimalistic framework for server-rendered Vue.js applications (inspired by Next.js)",
|
||||
"contributors": [
|
||||
{
|
||||
@ -64,20 +64,18 @@
|
||||
"npm": ">=3.10.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"@nuxtjs/youch": "3.0.2",
|
||||
"@nuxtjs/youch": "3.1.0",
|
||||
"ansi-html": "^0.0.7",
|
||||
"autoprefixer": "^7.1.3",
|
||||
"babel-core": "^6.26.0",
|
||||
"babel-loader": "^7.1.2",
|
||||
"babel-preset-es2015": "^6.24.1",
|
||||
"babel-preset-vue-app": "^1.2.1",
|
||||
"bulma": "^0.5.1",
|
||||
"babel-preset-vue-app": "^1.3.0",
|
||||
"chalk": "^2.1.0",
|
||||
"chokidar": "^1.7.0",
|
||||
"clone": "^2.1.1",
|
||||
"compression": "^1.7.0",
|
||||
"connect": "^3.6.3",
|
||||
"css-loader": "https://github.com/nuxt/css-loader.git",
|
||||
"css-loader": "^0.28.7",
|
||||
"debug": "^3.0.1",
|
||||
"es6-promise": "^4.1.1",
|
||||
"etag": "^1.8.0",
|
||||
@ -94,6 +92,7 @@
|
||||
"lru-cache": "^4.1.1",
|
||||
"memory-fs": "^0.4.1",
|
||||
"minimist": "^1.2.0",
|
||||
"open-in-editor": "^2.2.0",
|
||||
"opencollective": "^1.0.3",
|
||||
"pify": "^3.0.0",
|
||||
"postcss": "^6.0.10",
|
||||
@ -107,7 +106,7 @@
|
||||
"serve-static": "^1.12.4",
|
||||
"server-destroy": "^1.0.1",
|
||||
"source-map": "^0.5.7",
|
||||
"source-map-support": "^0.4.16",
|
||||
"source-map-support": "^0.4.17",
|
||||
"tappable": "^1.1.0",
|
||||
"url-loader": "^0.5.9",
|
||||
"vue": "~2.4.2",
|
||||
@ -129,13 +128,12 @@
|
||||
"babel-plugin-array-includes": "^2.0.3",
|
||||
"babel-plugin-external-helpers": "^6.22.0",
|
||||
"babel-plugin-istanbul": "^4.1.4",
|
||||
"babel-preset-es2015": "^6.24.1",
|
||||
"codecov": "^2.3.0",
|
||||
"copy-webpack-plugin": "^4.0.1",
|
||||
"cross-env": "^5.0.5",
|
||||
"eslint": "^4.5.0",
|
||||
"eslint": "^4.6.1",
|
||||
"eslint-config-standard": "^10.2.1",
|
||||
"eslint-plugin-html": "^3.2.0",
|
||||
"eslint-plugin-html": "^3.2.1",
|
||||
"eslint-plugin-import": "^2.7.0",
|
||||
"eslint-plugin-node": "^5.1.1",
|
||||
"eslint-plugin-promise": "^3.5.0",
|
||||
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "nuxt-start",
|
||||
"version": "1.0.0-rc7",
|
||||
"version": "1.0.0-rc11",
|
||||
"description": "runtime-only build for nuxt",
|
||||
"contributors": [
|
||||
{
|
||||
@ -46,8 +46,9 @@
|
||||
"npm": ">=3.10.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"source-map-support": "^0.4.16",
|
||||
"source-map-support": "^0.4.17",
|
||||
"pretty-error": "^2.1.1",
|
||||
"minimist": "^1.2.0",
|
||||
"lodash": "^4.17.4",
|
||||
"hash-sum": "^1.0.2",
|
||||
"tappable": "^1.1.0",
|
||||
|
@ -119,7 +119,7 @@ test('/error status code', async t => {
|
||||
await rp(url('/error'))
|
||||
} catch (err) {
|
||||
t.true(err.statusCode === 500)
|
||||
t.true(err.response.body.includes('Error mouahahah'))
|
||||
t.true(err.response.body.includes('An error occurred in the application and your page could not be served'))
|
||||
}
|
||||
})
|
||||
|
||||
|
@ -29,7 +29,7 @@ test('/ should display an error', async t => {
|
||||
|
||||
test('/404 should display an error too', async t => {
|
||||
let { error } = await nuxt.renderRoute('/404')
|
||||
t.true(error.message.includes('This page could not be found.'))
|
||||
t.true(error.message.includes('This page could not be found'))
|
||||
})
|
||||
|
||||
test('/ with renderAndGetWindow()', async t => {
|
||||
|
7
test/fixtures/with-config/assets/app.css
vendored
7
test/fixtures/with-config/assets/app.css
vendored
@ -1,3 +1,10 @@
|
||||
.global-css-selector {
|
||||
color: red;
|
||||
}
|
||||
|
||||
.test-enter-active, .test-leave-active {
|
||||
transition: opacity .5s
|
||||
}
|
||||
.test-enter, .test-leave-active {
|
||||
opacity: 0
|
||||
}
|
||||
|
BIN
test/fixtures/with-config/assets/roboto.woff2
vendored
Normal file
BIN
test/fixtures/with-config/assets/roboto.woff2
vendored
Normal file
Binary file not shown.
14
test/fixtures/with-config/layouts/default.vue
vendored
14
test/fixtures/with-config/layouts/default.vue
vendored
@ -4,3 +4,17 @@
|
||||
<nuxt/>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style>
|
||||
@font-face {
|
||||
font-family: 'Roboto';
|
||||
font-style: normal;
|
||||
font-weight: 400;
|
||||
src: local('Roboto'), local('Roboto-Regular'), url(~/assets/roboto.woff2) format('woff2');
|
||||
unicode-range: U+0460-052F, U+20B4, U+2DE0-2DFF, U+A640-A69F;
|
||||
}
|
||||
|
||||
body {
|
||||
font-family: 'Roboto';
|
||||
}
|
||||
</style>
|
18
test/fixtures/with-config/nuxt.config.js
vendored
18
test/fixtures/with-config/nuxt.config.js
vendored
@ -15,6 +15,7 @@ module.exports = {
|
||||
}
|
||||
},
|
||||
transition: 'test',
|
||||
layoutTransition: 'test',
|
||||
offline: true,
|
||||
plugins: [
|
||||
'~/plugins/test.js',
|
||||
@ -24,10 +25,18 @@ module.exports = {
|
||||
env: {
|
||||
bool: true,
|
||||
num: 23,
|
||||
string: 'Nuxt.js'
|
||||
string: 'Nuxt.js',
|
||||
object: {
|
||||
bool: false,
|
||||
string: 'ok',
|
||||
num2: 8.23,
|
||||
obj: {
|
||||
again: true
|
||||
}
|
||||
}
|
||||
},
|
||||
build: {
|
||||
extractCSS: true,
|
||||
// extractCSS: true,
|
||||
publicPath: '/orion/',
|
||||
analyze: {
|
||||
analyzerMode: 'disabled',
|
||||
@ -46,6 +55,11 @@ module.exports = {
|
||||
http2: {
|
||||
push: true
|
||||
},
|
||||
bundleRenderer: {
|
||||
shouldPreload: (file, type) => {
|
||||
return ['script', 'style', 'font'].includes(type)
|
||||
}
|
||||
},
|
||||
static: {
|
||||
maxAge: '1y'
|
||||
}
|
||||
|
9
test/fixtures/with-config/pages/env.vue
vendored
9
test/fixtures/with-config/pages/env.vue
vendored
@ -1,11 +1,20 @@
|
||||
<template>
|
||||
<div>
|
||||
<pre>{{ env }}</pre>
|
||||
<p>object:</p>
|
||||
<pre>{{ processEnv }}</pre>
|
||||
<nuxt-link to="/">Home</nuxt-link>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
layout: 'custom-env',
|
||||
data() {
|
||||
return { processEnv: process.env.object }
|
||||
},
|
||||
asyncData ({ env }) {
|
||||
delete env.object
|
||||
return { env }
|
||||
}
|
||||
}
|
||||
|
@ -26,9 +26,13 @@ test('/', async t => {
|
||||
})
|
||||
|
||||
test('/ (global styles inlined)', async t => {
|
||||
// const { html } = await nuxt.renderRoute('/')
|
||||
// t.true(html.includes('.global-css-selector'))
|
||||
t.pass()
|
||||
const { html } = await nuxt.renderRoute('/')
|
||||
t.true(html.includes('.global-css-selector'))
|
||||
})
|
||||
|
||||
test('/ (preload fonts)', async t => {
|
||||
const { html } = await nuxt.renderRoute('/')
|
||||
t.true(html.includes('<link rel="preload" href="/test/orion/fonts/roboto.7cf5d7c.woff2" as="font" type="font/woff2" crossorigin'))
|
||||
})
|
||||
|
||||
test('/ (custom app.html)', async t => {
|
||||
@ -64,6 +68,10 @@ test('/test/env', async t => {
|
||||
t.true(html.includes('"bool": true'))
|
||||
t.true(html.includes('"num": 23'))
|
||||
t.true(html.includes('"string": "Nuxt.js"'))
|
||||
t.true(html.includes('"bool": false'))
|
||||
t.true(html.includes('"string": "ok"'))
|
||||
t.true(html.includes('"num2": 8.23'))
|
||||
t.true(html.includes('"obj": {'))
|
||||
})
|
||||
|
||||
test('/test/error', async t => {
|
||||
@ -87,7 +95,7 @@ test('/test/about-bis (added with extendRoutes)', async t => {
|
||||
|
||||
test('Check stats.json generated by build.analyze', t => {
|
||||
const stats = require(resolve(__dirname, 'fixtures/with-config/.nuxt/dist/stats.json'))
|
||||
t.is(stats.assets.length, 28)
|
||||
t.is(stats.assets.length, 27)
|
||||
})
|
||||
|
||||
test('Check /test/test.txt with custom serve-static options', async t => {
|
||||
|
100
yarn.lock
100
yarn.lock
@ -961,9 +961,9 @@ babel-preset-es2015@^6.24.1:
|
||||
babel-plugin-transform-es2015-unicode-regex "^6.24.1"
|
||||
babel-plugin-transform-regenerator "^6.24.1"
|
||||
|
||||
babel-preset-vue-app@^1.2.1:
|
||||
version "1.2.1"
|
||||
resolved "https://registry.yarnpkg.com/babel-preset-vue-app/-/babel-preset-vue-app-1.2.1.tgz#2f6b71890a21a675019ca1db8d0da15bf017ba24"
|
||||
babel-preset-vue-app@^1.3.0:
|
||||
version "1.3.0"
|
||||
resolved "https://registry.yarnpkg.com/babel-preset-vue-app/-/babel-preset-vue-app-1.3.0.tgz#4b31f690a353c8735963e06927a072a0bb82126f"
|
||||
dependencies:
|
||||
babel-plugin-syntax-dynamic-import "^6.18.0"
|
||||
babel-plugin-transform-object-rest-spread "^6.26.0"
|
||||
@ -1220,10 +1220,6 @@ builtin-status-codes@^3.0.0:
|
||||
version "3.0.0"
|
||||
resolved "https://registry.yarnpkg.com/builtin-status-codes/-/builtin-status-codes-3.0.0.tgz#85982878e21b98e1c66425e03d0174788f569ee8"
|
||||
|
||||
bulma@^0.5.1:
|
||||
version "0.5.1"
|
||||
resolved "https://registry.yarnpkg.com/bulma/-/bulma-0.5.1.tgz#db2831c94afe732250c7b12527a7b792a4dc9ef8"
|
||||
|
||||
bytes@2.5.0:
|
||||
version "2.5.0"
|
||||
resolved "https://registry.yarnpkg.com/bytes/-/bytes-2.5.0.tgz#4c9423ea2d252c270c41b2bdefeff9bb6b62c06a"
|
||||
@ -1308,12 +1304,12 @@ caniuse-api@^2.0.0:
|
||||
lodash.uniq "^4.5.0"
|
||||
|
||||
caniuse-db@^1.0.30000529, caniuse-db@^1.0.30000634, caniuse-db@^1.0.30000639:
|
||||
version "1.0.30000718"
|
||||
resolved "https://registry.yarnpkg.com/caniuse-db/-/caniuse-db-1.0.30000718.tgz#86cdd97987302554934c61e106f4e470f16f993c"
|
||||
version "1.0.30000721"
|
||||
resolved "https://registry.yarnpkg.com/caniuse-db/-/caniuse-db-1.0.30000721.tgz#cdc52efe8f82dd13916615b78e86f704ece61802"
|
||||
|
||||
caniuse-lite@^1.0.0, caniuse-lite@^1.0.30000718:
|
||||
version "1.0.30000718"
|
||||
resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30000718.tgz#0dd24290beb11310b2d80f6b70a823c2a65a6fad"
|
||||
version "1.0.30000721"
|
||||
resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30000721.tgz#931a21a7bd85016300328d21f126d84b73437d35"
|
||||
|
||||
capture-stack-trace@^1.0.0:
|
||||
version "1.0.0"
|
||||
@ -1348,7 +1344,7 @@ chalk@^0.4.0:
|
||||
has-color "~0.1.0"
|
||||
strip-ansi "~0.1.0"
|
||||
|
||||
chalk@^2.0.0, chalk@^2.0.1, chalk@^2.1.0:
|
||||
chalk@^2.0.1, chalk@^2.1.0:
|
||||
version "2.1.0"
|
||||
resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.1.0.tgz#ac5becf14fa21b99c6c92ca7a7d7cfd5b17e743e"
|
||||
dependencies:
|
||||
@ -1815,9 +1811,9 @@ css-color-names@0.0.4:
|
||||
version "0.0.4"
|
||||
resolved "https://registry.yarnpkg.com/css-color-names/-/css-color-names-0.0.4.tgz#808adc2e79cf84738069b646cb20ec27beb629e0"
|
||||
|
||||
"css-loader@https://github.com/nuxt/css-loader.git":
|
||||
version "0.28.5"
|
||||
resolved "https://github.com/nuxt/css-loader.git#43674428e42dd208f6192cfc0b1679935a0bae4b"
|
||||
css-loader@^0.28.7:
|
||||
version "0.28.7"
|
||||
resolved "https://registry.yarnpkg.com/css-loader/-/css-loader-0.28.7.tgz#5f2ee989dd32edd907717f953317656160999c1b"
|
||||
dependencies:
|
||||
babel-code-frame "^6.11.0"
|
||||
css-selector-tokenizer "^0.7.0"
|
||||
@ -2354,11 +2350,12 @@ eslint-module-utils@^2.1.1:
|
||||
debug "^2.6.8"
|
||||
pkg-dir "^1.0.0"
|
||||
|
||||
eslint-plugin-html@^3.2.0:
|
||||
version "3.2.0"
|
||||
resolved "https://registry.yarnpkg.com/eslint-plugin-html/-/eslint-plugin-html-3.2.0.tgz#fb64c2789e9582b97f580a38814a57966f91a7b2"
|
||||
eslint-plugin-html@^3.2.1:
|
||||
version "3.2.1"
|
||||
resolved "https://registry.yarnpkg.com/eslint-plugin-html/-/eslint-plugin-html-3.2.1.tgz#4289d38245f3d95134d22c17b1894d78db92c572"
|
||||
dependencies:
|
||||
htmlparser2 "^3.8.2"
|
||||
semver "^5.4.1"
|
||||
|
||||
eslint-plugin-import@^2.7.0:
|
||||
version "2.7.0"
|
||||
@ -2399,9 +2396,9 @@ eslint-scope@^3.7.1:
|
||||
esrecurse "^4.1.0"
|
||||
estraverse "^4.1.1"
|
||||
|
||||
eslint@^4.5.0:
|
||||
version "4.5.0"
|
||||
resolved "https://registry.yarnpkg.com/eslint/-/eslint-4.5.0.tgz#bb75d3b8bde97fb5e13efcd539744677feb019c3"
|
||||
eslint@^4.6.1:
|
||||
version "4.6.1"
|
||||
resolved "https://registry.yarnpkg.com/eslint/-/eslint-4.6.1.tgz#ddc7fc7fd70bf93205b0b3449bb16a1e9e7d4950"
|
||||
dependencies:
|
||||
ajv "^5.2.0"
|
||||
babel-code-frame "^6.22.0"
|
||||
@ -2591,7 +2588,7 @@ extend@~3.0.0:
|
||||
version "3.0.1"
|
||||
resolved "https://registry.yarnpkg.com/extend/-/extend-3.0.1.tgz#a755ea7bc1adfcc5a31ce7e762dbaadc5e636444"
|
||||
|
||||
external-editor@^2.0.1, external-editor@^2.0.4:
|
||||
external-editor@^2.0.1:
|
||||
version "2.0.4"
|
||||
resolved "https://registry.yarnpkg.com/external-editor/-/external-editor-2.0.4.tgz#1ed9199da9cbfe2ef2f7a31b2fde8b0d12368972"
|
||||
dependencies:
|
||||
@ -3249,7 +3246,7 @@ ini@^1.3.4, ini@~1.3.0:
|
||||
version "1.3.4"
|
||||
resolved "https://registry.yarnpkg.com/ini/-/ini-1.3.4.tgz#0537cb79daf59b59a1a517dff706c86ec039162e"
|
||||
|
||||
inquirer@3.0.6:
|
||||
inquirer@3.0.6, inquirer@^3.0.6:
|
||||
version "3.0.6"
|
||||
resolved "https://registry.yarnpkg.com/inquirer/-/inquirer-3.0.6.tgz#e04aaa9d05b7a3cb9b0f407d04375f0447190347"
|
||||
dependencies:
|
||||
@ -3267,25 +3264,6 @@ inquirer@3.0.6:
|
||||
strip-ansi "^3.0.0"
|
||||
through "^2.3.6"
|
||||
|
||||
inquirer@^3.0.6:
|
||||
version "3.2.2"
|
||||
resolved "https://registry.yarnpkg.com/inquirer/-/inquirer-3.2.2.tgz#c2aaede1507cc54d826818737742d621bef2e823"
|
||||
dependencies:
|
||||
ansi-escapes "^2.0.0"
|
||||
chalk "^2.0.0"
|
||||
cli-cursor "^2.1.0"
|
||||
cli-width "^2.0.0"
|
||||
external-editor "^2.0.4"
|
||||
figures "^2.0.0"
|
||||
lodash "^4.3.0"
|
||||
mute-stream "0.0.7"
|
||||
run-async "^2.2.0"
|
||||
rx-lite "^4.0.8"
|
||||
rx-lite-aggregates "^4.0.8"
|
||||
string-width "^2.1.0"
|
||||
strip-ansi "^4.0.0"
|
||||
through "^2.3.6"
|
||||
|
||||
interpret@^1.0.0:
|
||||
version "1.0.3"
|
||||
resolved "https://registry.yarnpkg.com/interpret/-/interpret-1.0.3.tgz#cbc35c62eeee73f19ab7b10a801511401afc0f90"
|
||||
@ -4090,7 +4068,7 @@ minimalistic-crypto-utils@^1.0.0, minimalistic-crypto-utils@^1.0.1:
|
||||
dependencies:
|
||||
brace-expansion "^1.1.7"
|
||||
|
||||
minimist@0.0.8:
|
||||
minimist@0.0.8, minimist@~0.0.1:
|
||||
version "0.0.8"
|
||||
resolved "https://registry.yarnpkg.com/minimist/-/minimist-0.0.8.tgz#857fcabfc3397d2625b8228262e86aa7a011b05d"
|
||||
|
||||
@ -4098,10 +4076,6 @@ minimist@1.2.0, minimist@^1.1.3, minimist@^1.2.0:
|
||||
version "1.2.0"
|
||||
resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.0.tgz#a35008b20f41383eec1fb914f4cd5df79a264284"
|
||||
|
||||
minimist@~0.0.1:
|
||||
version "0.0.10"
|
||||
resolved "https://registry.yarnpkg.com/minimist/-/minimist-0.0.10.tgz#de3f98543dbf96082be48ad1a0c7cda836301dcf"
|
||||
|
||||
"mkdirp@>=0.5 0", mkdirp@^0.5.0, mkdirp@^0.5.1, mkdirp@~0.5.0, mkdirp@~0.5.1:
|
||||
version "0.5.1"
|
||||
resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.1.tgz#30057438eac6cf7f8c4767f38648d6697d75c903"
|
||||
@ -4130,8 +4104,8 @@ mute-stream@0.0.7:
|
||||
resolved "https://registry.yarnpkg.com/mute-stream/-/mute-stream-0.0.7.tgz#3075ce93bc21b8fab43e1bc4da7e8115ed1e7bab"
|
||||
|
||||
nan@^2.3.0:
|
||||
version "2.6.2"
|
||||
resolved "https://registry.yarnpkg.com/nan/-/nan-2.6.2.tgz#e4ff34e6c95fdfb5aecc08de6596f43605a7db45"
|
||||
version "2.7.0"
|
||||
resolved "https://registry.yarnpkg.com/nan/-/nan-2.7.0.tgz#d95bf721ec877e08db276ed3fc6eb78f9083ad46"
|
||||
|
||||
natural-compare@^1.4.0:
|
||||
version "1.4.0"
|
||||
@ -5748,16 +5722,6 @@ run-async@^2.2.0:
|
||||
dependencies:
|
||||
is-promise "^2.1.0"
|
||||
|
||||
rx-lite-aggregates@^4.0.8:
|
||||
version "4.0.8"
|
||||
resolved "https://registry.yarnpkg.com/rx-lite-aggregates/-/rx-lite-aggregates-4.0.8.tgz#753b87a89a11c95467c4ac1626c4efc4e05c67be"
|
||||
dependencies:
|
||||
rx-lite "*"
|
||||
|
||||
rx-lite@*, rx-lite@^4.0.8:
|
||||
version "4.0.8"
|
||||
resolved "https://registry.yarnpkg.com/rx-lite/-/rx-lite-4.0.8.tgz#0b1e11af8bc44836f04a6407e92da42467b79444"
|
||||
|
||||
rx@^4.1.0:
|
||||
version "4.1.0"
|
||||
resolved "https://registry.yarnpkg.com/rx/-/rx-4.1.0.tgz#a5f13ff79ef3b740fe30aa803fb09f98805d4782"
|
||||
@ -5786,7 +5750,7 @@ semver-diff@^2.0.0:
|
||||
dependencies:
|
||||
semver "^5.0.3"
|
||||
|
||||
"semver@2 || 3 || 4 || 5", semver@^5.0.3, semver@^5.1.0, semver@^5.3.0:
|
||||
"semver@2 || 3 || 4 || 5", semver@^5.0.3, semver@^5.1.0, semver@^5.3.0, semver@^5.4.1:
|
||||
version "5.4.1"
|
||||
resolved "https://registry.yarnpkg.com/semver/-/semver-5.4.1.tgz#e059c09d8571f0540823733433505d3a2f00b18e"
|
||||
|
||||
@ -5915,12 +5879,18 @@ source-list-map@^2.0.0:
|
||||
version "2.0.0"
|
||||
resolved "https://registry.yarnpkg.com/source-list-map/-/source-list-map-2.0.0.tgz#aaa47403f7b245a92fbc97ea08f250d6087ed085"
|
||||
|
||||
source-map-support@^0.4.0, source-map-support@^0.4.15, source-map-support@^0.4.16:
|
||||
source-map-support@^0.4.0, source-map-support@^0.4.15:
|
||||
version "0.4.16"
|
||||
resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.4.16.tgz#16fecf98212467d017d586a2af68d628b9421cd8"
|
||||
dependencies:
|
||||
source-map "^0.5.6"
|
||||
|
||||
source-map-support@^0.4.17:
|
||||
version "0.4.17"
|
||||
resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.4.17.tgz#6f2150553e6375375d0ccb3180502b78c18ba430"
|
||||
dependencies:
|
||||
source-map "^0.5.6"
|
||||
|
||||
source-map@0.5.6:
|
||||
version "0.5.6"
|
||||
resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.5.6.tgz#75ce38f52bf0733c5a7f0c118d81334a2bb5f412"
|
||||
@ -6045,7 +6015,7 @@ string-width@^1.0.1, string-width@^1.0.2:
|
||||
is-fullwidth-code-point "^1.0.0"
|
||||
strip-ansi "^3.0.0"
|
||||
|
||||
string-width@^2.0.0, string-width@^2.1.0:
|
||||
string-width@^2.0.0:
|
||||
version "2.1.1"
|
||||
resolved "https://registry.yarnpkg.com/string-width/-/string-width-2.1.1.tgz#ab93f27a8dc13d28cac815c462143a6d9012ae9e"
|
||||
dependencies:
|
||||
@ -6725,14 +6695,10 @@ window-size@0.1.0:
|
||||
version "0.1.0"
|
||||
resolved "https://registry.yarnpkg.com/window-size/-/window-size-0.1.0.tgz#5438cd2ea93b202efa3a19fe8887aee7c94f9c9d"
|
||||
|
||||
wordwrap@0.0.2:
|
||||
wordwrap@0.0.2, wordwrap@~0.0.2:
|
||||
version "0.0.2"
|
||||
resolved "https://registry.yarnpkg.com/wordwrap/-/wordwrap-0.0.2.tgz#b79669bb42ecb409f83d583cad52ca17eaa1643f"
|
||||
|
||||
wordwrap@~0.0.2:
|
||||
version "0.0.3"
|
||||
resolved "https://registry.yarnpkg.com/wordwrap/-/wordwrap-0.0.3.tgz#a3d5da6cd5c0bc0008d37234bbaf1bed63059107"
|
||||
|
||||
wordwrap@~1.0.0:
|
||||
version "1.0.0"
|
||||
resolved "https://registry.yarnpkg.com/wordwrap/-/wordwrap-1.0.0.tgz#27584810891456a4171c8d0226441ade90cbcaeb"
|
||||
|
Loading…
Reference in New Issue
Block a user