Merge pull request #1 from nuxt/dev

Merge upstream nuxt/nuxt.js:dev
This commit is contained in:
Thomas Marrec 2017-11-17 10:54:15 +11:00 committed by GitHub
commit 682169625f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
60 changed files with 909 additions and 482 deletions

View File

@ -1,3 +0,0 @@
# Updating headers with Nuxt.js
https://nuxtjs.org/examples/seo-html-head

View File

@ -17,14 +17,14 @@ body {
}
.layout-enter-active, .layout-leave-active {
transition: opacity .5s
transition: opacity 0.5s
}
.layout-enter, .layout-leave-active {
opacity: 0
}
.bounce-enter-active {
animation: bounce-in .8s;
animation: bounce-in .5s;
}
.bounce-leave-active {
animation: bounce-out .5s;

View File

@ -1,11 +1,6 @@
<template>
<div>
<menu>
<ul>
<li>Option 1</li>
<li>Option 2</li>
</ul>
</menu>
<h1>Secondary Layout</h1>
<nuxt/>
</div>
</template>

View File

@ -5,7 +5,7 @@
"nuxt": "latest"
},
"scripts": {
"dev": "../../bin/nuxt",
"dev": "nuxt",
"build": "nuxt build",
"start": "nuxt start"
}

View File

@ -3,5 +3,6 @@
<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>
<p><nuxt-link to="/users-2">Lists of users #2 (with `watch`)</nuxt-link></p>
</div>
</template>

View File

@ -0,0 +1,91 @@
<template>
<div class="container">
<nuxt-link v-if="page > 1" :to="'?page=' + (page - 1)">&lt; Prev</nuxt-link>
<a v-else class="disabled">&lt; Prev</a>
<span>{{ page }}/{{ totalPages }}</span>
<nuxt-link v-if="page < totalPages" :to="'?page=' + (page + 1)">Next &gt;</nuxt-link>
<a v-else class="disabled">Next &gt;</a>
<transition mode="out-in" :name="transitionName">
<ul :key="page">
<li v-for="user in users" :key="user.id">
<img :src="user.avatar" class="avatar" />
<span>{{ user.first_name }} {{ user.last_name }}</span>
</li>
</ul>
</transition>
<p><nuxt-link to="/">Back home</nuxt-link></p>
</div>
</template>
<script>
import axios from 'axios'
export default {
watch: {
'$route.query.page': async function (page) {
this.$nuxt.$loading.start()
const { data } = await axios.get(`https://reqres.in/api/users?page=${page}`)
this.users = data.data
this.transitionName = this.getTransitionName(page)
this.page = +(page || 1)
this.totalPages = data.total_pages
this.$nuxt.$loading.finish()
}
},
async asyncData({ query }) {
const page = +(query.page || 1)
const { data } = await axios.get(`https://reqres.in/api/users?page=${page}`)
return {
page,
totalPages: data.total_pages,
users: data.data
}
},
data() {
return {
transitionName: this.getTransitionName(this.page)
}
},
methods: {
getTransitionName(newPage) {
return newPage < this.page ? 'slide-right' : 'slide-left'
}
}
}
</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;
transition: all .5s cubic-bezier(.55,0,.1,1);
}
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>

View File

@ -6,7 +6,7 @@
<nuxt-link v-if="page < totalPages" :to="'?page=' + (page + 1)">Next &gt;</nuxt-link>
<a v-else class="disabled">Next &gt;</a>
<ul>
<li v-for="user in users">
<li v-for="user in users" :key="user.id">
<img :src="user.avatar" class="avatar" />
<span>{{ user.first_name }} {{ user.last_name }}</span>
</li>
@ -19,15 +19,20 @@
import axios from 'axios'
export default {
// Watch for $route.query.page to call Component methods (asyncData, fetch, validate, layout, etc.)
watchQuery: ['page'],
// Key for <nuxt-child> (transitions)
key: (to) => to.fullPath,
// Called to know which transition to apply
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 page = +(query.page || 1)
const { data } = await axios.get(`https://reqres.in/api/users?page=${page}`)
return {
page: +data.page,
page,
totalPages: data.total_pages,
users: data.data
}

View File

@ -0,0 +1,13 @@
# Manage your app's meta information
Nuxt.js uses [vue-meta](https://github.com/declandewet/vue-meta) to manage page meta info (such as: meta, title, link, style, script) of your application.
## Example
SEO: https://nuxtjs.org/examples/seo-html-head
## Documentation
Nuxt.js: https://nuxtjs.org/guide/views#html-head
vue-meta: https://github.com/declandewet/vue-meta#table-of-contents

View File

@ -11,6 +11,12 @@ export default {
title: 'Home page 🚀',
meta: [
{ hid: 'description', name: 'description', content: 'Home page description' }
],
script: [
{ src: '/head.js' },
// Supported since 1.0
{ src: '/body.js', body: true },
{ src: '/defer.js', defer: '' }
]
}
}

View File

@ -0,0 +1 @@
console.log('about.js loaded!') // eslint-disable-line no-console

View File

@ -0,0 +1 @@
console.log('body.js loaded!') // eslint-disable-line no-console

View File

@ -0,0 +1 @@
console.log('defer.js loaded!') // eslint-disable-line no-console

View File

@ -0,0 +1 @@
console.log('head.js loaded!') // eslint-disable-line no-console

View File

@ -4,42 +4,54 @@
*
* You can see the styles here:
* https://github.com/tailwindcss/tailwindcss/blob/master/css/preflight.css
*
* If using `postcss-import`, you should import this line from it's own file:
*
* @import "./tailwind-preflight.css";
*
* See: https://github.com/tailwindcss/tailwindcss/issues/53#issuecomment-341413622
*/
@tailwind preflight;
/**
* Here you would add any of your custom component classes; stuff that you'd
* want loaded *before* the utilities so that the utilities could still
* override them.
*
* Example:
*
* .btn { ... }
* .form-input { ... }
*
* Or if using a preprocessor:
*
* @import "components/buttons";
* @import "components/forms";
*/
/**
* Here you would add any of your custom component classes; stuff that you'd
* want loaded *before* the utilities so that the utilities could still
* override them.
*
* Example:
*
* .btn { ... }
* .form-input { ... }
*
* Or if using a preprocessor or `postcss-import`:
*
* @import "components/buttons";
* @import "components/forms";
*/
/**
* This injects all of Tailwind's utility classes, generated based on your
* config file.
*/
@tailwind utilities;
/**
* This injects all of Tailwind's utility classes, generated based on your
* config file.
*
* If using `postcss-import`, you should import this line from it's own file:
*
* @import "./tailwind-utilities.css";
*
* See: https://github.com/tailwindcss/tailwindcss/issues/53#issuecomment-341413622
*/
@tailwind utilities;
/**
* Here you would add any custom utilities you need that don't come out of the
* box with Tailwind.
*
* Example :
*
* .bg-pattern-graph-paper { ... }
* .skew-45 { ... }
*
* Or if using a preprocessor..
*
* @import "utilities/backgrond-patterns";
* @import "utilities/skew-transforms";
*/
/**
* Here you would add any custom utilities you need that don't come out of the
* box with Tailwind.
*
* Example :
*
* .bg-pattern-graph-paper { ... }
* .skew-45 { ... }
*
* Or if using a preprocessor or `postcss-import`:
*
* @import "utilities/background-patterns";
* @import "utilities/skew-transforms";
*/

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.2 KiB

View File

@ -0,0 +1,11 @@
module.exports = {
/*
** Customize the progress bar color
*/
loading: { color: '#3B8070' },
mode: 'spa',
plugins: ['~plugins/buefy'],
router: {
linkActiveClass: 'is-active'
}
}

View File

@ -0,0 +1,20 @@
{
"name": "with-buefy",
"version": "1.0.0",
"main": "index.js",
"license": "MIT",
"scripts": {
"dev": "nuxt",
"build": "nuxt build",
"start": "nuxt start"
},
"dependencies": {
"buefy": "^0.5.4",
"nuxt": "latest",
"vue": "~2.4.4"
},
"devDependencies": {
"node-sass": "^4.6.0",
"sass-loader": "^6.0.6"
}
}

View File

@ -0,0 +1,3 @@
<template>
<h1>About</h1>
</template>

View File

@ -0,0 +1,25 @@
<template>
<nav class="navbar has-shadow is-light">
<div class="container">
<div class="navbar-brand">
<nuxt-link to="/" class="navbar-item">
<img src="~/assets/logo.png">
</nuxt-link>
</div>
<div class="navbar-menu">
<div class="navbar-start">
<nuxt-link to="/" class="navbar-item is-tab" exact>Home</nuxt-link>
<nuxt-link to="/about" class="navbar-item is-tab" exact>About</nuxt-link>
</div>
</div>
</div>
</nav>
</template>
<style lang="scss">
$primary: blue;
$navbar-tab-active-border-bottom-color: red;
@import "~bulma";
@import "~buefy/src/scss/buefy";
</style>

View File

@ -0,0 +1,4 @@
import Vue from 'vue'
import Buefy from 'buefy'
Vue.use(Buefy)

View File

@ -0,0 +1,10 @@
<template>
<el-card class="box-card">
<div slot="header" class="clearfix">
<span>Element Example</span>
</div>
<div>
<nuxt></nuxt>
</div>
</el-card>
</template>

View File

@ -0,0 +1,15 @@
module.exports = {
/*
** Global CSS
*/
css: [
'element-ui/lib/theme-default/index.css'
],
/*
** Add element-ui in our app, see plugins/element-ui.js file
*/
plugins: [
'@/plugins/element-ui'
]
}

View File

@ -0,0 +1,18 @@
{
"name": "with-element-ui",
"version": "1.0.0",
"license": "MIT",
"dependencies": {
"element-ui": "^1.4.9",
"nuxt": "latest"
},
"scripts": {
"dev": "nuxt",
"build": "nuxt build",
"start": "nuxt start"
},
"devDependencies": {
"node-sass": "^4.6.0",
"sass-loader": "^6.0.6"
}
}

View File

@ -0,0 +1,100 @@
<template>
<div class="elm-demo">
<el-form :model="account" :rules="formRules" ref="elm-demo" label-width="100px">
<el-row type="flex" justify="flex-start">
<el-col :xs="24" :sm="10">
<el-form-item label="Account Name" prop="name" required>
<el-input v-model="account.name"></el-input>
</el-form-item>
</el-col>
</el-row>
<el-row type="flex" justify="flex-start">
<el-col :xs="24" :sm="10">
<el-form-item label="Date" prop="date" required>
<el-date-picker v-model="account.date" style="width: 100%;"></el-date-picker>
</el-form-item>
</el-col>
<el-col :xs="24" :sm="{span: 3, offset: 2}">
<el-form-item label="Subscribe" prop="subscribe">
<el-switch on-text="" off-text="" v-model="account.subscribe"></el-switch>
</el-form-item>
</el-col>
</el-row>
<el-row type="flex" justify="flex-start">
<el-col :xs="24" :sm="10">
<el-form-item label="Rate" prop="rate">
<el-rate v-model="account.rate" :colors="['#99A9BF', '#F7BA2A', '#FF9900']"></el-rate>
</el-form-item>
</el-col>
<el-col :xs="24" :sm="{span: 10, offset: 2}">
<el-form-item label="Priority" prop="priority">
<el-radio-group v-model="account.priority">
<el-radio label="m">Medium</el-radio>
<el-radio label="h">High</el-radio>
</el-radio-group>
</el-form-item>
</el-col>
</el-row>
<el-row type="flex" justify="center">
<el-button type="primary" @click="submit('elm-demo')">Create</el-button>
<el-button @click="reset('elm-demo')">Reset</el-button>
</el-row>
</el-form>
</div>
</template>
<script>
export default {
data() {
return {
account: {
name: '',
date: '',
subscribe: false,
priority: 'm',
rate: 5
},
formRules: {
name: [
{ required: true, message: 'Account is required', trigger: 'blur' },
{ min: 6, message: 'Account\'s length is at least 6', trigger: 'blur' }
]
}
}
},
methods: {
submit(formName) {
this.$refs[formName].validate((valid) => {
if (valid) {
this.$message.success('Create successfully !')
if (formName === 'popForm') {
this.popVisible = false
}
return false
} else {
this.$message.warning('Create failed')
return false
}
})
},
reset(formName) {
this.$refs[formName].resetFields()
}
}
}
</script>
<style lang="scss" scoped>
.el-select {
display: block
}
@media (max-width: 768px) {
.el-row {
flex-direction:column;
.el-button+.el-button {
margin-left: 0px;
margin-top: 15px;
}
}
}
</style>

View File

@ -0,0 +1,7 @@
import Vue from 'vue'
import Element from 'element-ui/lib/element-ui.common'
import locale from 'element-ui/lib/locale/lang/en'
export default () => {
Vue.use(Element, { locale })
}

View File

@ -15,19 +15,23 @@ layoutsKeys.forEach(function (key, i) { %>
let resolvedLayouts = {}
export default {
head: <%= serialize(head).replace('titleTemplate(', 'function(') %>,
head: <%= serialize(head).replace('head(', 'function(').replace('titleTemplate(', 'function(') %>,
render(h, props) {
<% if (loading) { %>const loadingEl = h('nuxt-loading', { ref: 'loading' })<% } %>
const layoutEl = h(this.nuxt.err ? 'nuxt' : this.layout, {
const layoutEl = h(this.layout || 'nuxt')
const templateEl = h('div', {
domProps: {
id: '__layout'
},
key: this.layoutName
})
}, [ layoutEl ])
const transitionEl = h('transition', {
props: {
name: '<%= layoutTransition.name %>',
mode: '<%= layoutTransition.mode %>'
}
}, [ layoutEl ])
}, [ templateEl ])
return h('div',{
domProps: {

View File

@ -6,13 +6,14 @@ import {
sanitizeComponent,
resolveRouteComponents,
getMatchedComponents,
getChangedComponentsInstances,
getMatchedComponentsInstances,
flatMapComponents,
setContext,
middlewareSeries,
promisify,
getLocation,
compile
compile,
getQueryDiff
} from './utils'
const noopData = () => { return {} }
@ -20,7 +21,6 @@ const noopFetch = () => {}
// Global shared references
let _lastPaths = []
let _lastComponentsFiles = []
let app
let router
<% if (store) { %>let store<% } %>
@ -99,6 +99,8 @@ function mapTransitions(Components, to, from) {
async function loadAsyncComponents (to, from, next) {
// Check if route path changed (this._pathChanged), only if the page is not an error (for validate())
this._pathChanged = !!app.nuxt.err || from.path !== to.path
this._queryChanged = JSON.stringify(to.query) !== JSON.stringify(from.query)
this._diffQuery = (this._queryChanged ? getQueryDiff(to.query, from.query) : [])
<% if (loading) { %>
if (this._pathChanged && this.$loading.start) {
@ -107,12 +109,30 @@ async function loadAsyncComponents (to, from, next) {
<% } %>
try {
await resolveRouteComponents(to)
const Components = await resolveRouteComponents(to)
<% if (loading) { %>
if (!this._pathChanged && this._queryChanged) {
// Add a marker on each component that it needs to refresh or not
const startLoader = Components.some((Component) => {
const watchQuery = Component.options.watchQuery
if (watchQuery === true) return true
if (Array.isArray(watchQuery)) {
return watchQuery.some((key) => this._diffQuery[key])
}
return false
})
if (startLoader && this.$loading.start) {
this.$loading.start()
}
}
<% } %>
// Call next()
next()
} catch (err) {
err = err || {}
const statusCode = err.statusCode || err.status || (err.response && err.response.status) || 500
this.error({ statusCode, message: err.message })
this.$nuxt.$emit('routeChanged', to, from, err)
next(false)
}
}
@ -172,7 +192,7 @@ function callMiddleware (Components, context, layout) {
}
async function render (to, from, next) {
if (this._pathChanged === false) return next()
if (this._pathChanged === false && this._queryChanged === false) return next()
// nextCalled is true when redirected
let nextCalled = false
@ -259,7 +279,20 @@ async function render (to, from, next) {
await Promise.all(Components.map((Component, i) => {
// Check if only children route changed
Component._path = compile(to.matched[i].path)(to.params)
if (!this._hadError && this._isMounted && Component._path === _lastPaths[i]) {
Component._dataRefresh = false
// Check if Component need to be refreshed (call asyncData & fetch)
// Only if its slug has changed or is watch query changes
if (this._pathChanged && Component._path !== _lastPaths[i]) {
Component._dataRefresh = true
} else if (!this._pathChanged && this._queryChanged) {
const watchQuery = Component.options.watchQuery
if (watchQuery === true) {
Component._dataRefresh = true
} else if (Array.isArray(watchQuery)) {
Component._dataRefresh = watchQuery.some((key) => this._diffQuery[key])
}
}
if (!this._hadError && this._isMounted && !Component._dataRefresh) {
return Promise.resolve()
}
@ -314,6 +347,7 @@ async function render (to, from, next) {
await this.loadLayout(layout)
this.error(error)
this.$nuxt.$emit('routeChanged', to, from, error)
next(false)
}
}
@ -347,26 +381,21 @@ function showNextPage(to) {
// When navigating on a different route but the same component is used, Vue.js
// Will not update the instance data, so we have to update $data ourselves
function fixPrepatch (to, from) {
if (this._pathChanged === false) return
function fixPrepatch(to, ___) {
if (this._pathChanged === false && this._queryChanged === false) return
Vue.nextTick(() => {
const instances = getChangedComponentsInstances(to, from)
const instances = getMatchedComponentsInstances(to)
var dlen = to.matched.length - instances.length
_lastComponentsFiles = instances.map((instance, i) => {
if (!instance) return '';
if (_lastPaths[dlen + i] === instance.constructor._path && typeof instance.constructor.options.data === 'function') {
instances.forEach((instance, i) => {
if (!instance) return
if (instance.constructor._dataRefresh && _lastPaths[i] === instance.constructor._path && typeof instance.constructor.options.data === 'function') {
const newData = instance.constructor.options.data.call(instance)
for (let key in newData) {
Vue.set(instance.$data, key, newData[key])
}
}
return instance.constructor.options.__file
})
showNextPage.call(this, to)
<% if (isDev) { %>
// Hot reloading
@ -375,19 +404,20 @@ function fixPrepatch (to, from) {
})
}
function nuxtReady (app) {
function nuxtReady (_app) {
window._nuxtReadyCbs.forEach((cb) => {
if (typeof cb === 'function') {
cb(app)
cb(_app)
}
})
// Special JSDOM
if (typeof window._onNuxtLoaded === 'function') {
window._onNuxtLoaded(app)
window._onNuxtLoaded(_app)
}
// Add router hooks
router.afterEach(function (to, from) {
app.$nuxt.$emit('routeChanged', to, from)
// Wait for fixPrepatch + $data updates
Vue.nextTick(() => _app.$nuxt.$emit('routeChanged', to, from))
})
}
@ -498,13 +528,15 @@ async function mountApp(__app) {
// Create Vue instance
const _app = new Vue(app)
// Load layout
<% if (mode !== 'spa') { %>
// Load layout
const layout = NUXT.layout || 'default'
await _app.loadLayout(layout)
_app.setLayout(layout)
<% } %>
// Mounts Vue app to DOM element
const mountApp = () => {
const mount = () => {
_app.$mount('#__nuxt')
// Listen for first Vue update
@ -523,7 +555,6 @@ async function mountApp(__app) {
if (Components.length) {
_app.setTransitions(mapTransitions(Components, router.currentRoute))
_lastPaths = router.currentRoute.matched.map(route => compile(route.path)(router.currentRoute.params))
_lastComponentsFiles = Components.map(Component => Component.options.__file)
}
// Initialize error handler
@ -538,7 +569,7 @@ async function mountApp(__app) {
// If page already is server rendered
if (NUXT.serverRendered) {
mountApp()
mount()
return
}
@ -549,11 +580,11 @@ async function mountApp(__app) {
normalizeComponents(router.currentRoute, router.currentRoute)
showNextPage.call(_app, router.currentRoute)
// Dont call fixPrepatch.call(_app, router.currentRoute, router.currentRoute) since it's first render
mountApp()
mount()
return
}
// Push the path and then mount app
router.push(path, () => mountApp(), (err) => console.error(err))
router.push(path, () => mount(), (err) => console.error(err))
})
}

View File

@ -2,26 +2,11 @@ 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
const defaultTransition = parent.$nuxt.nuxt.defaultTransition
let depth = 0
while (parent) {
if (parent.$vnode && parent.$vnode.data.nuxtChild) {
@ -44,14 +29,12 @@ export default {
}
})
nuxt._childVnode = h('transition', {
return h('transition', {
props: transitionProps,
on: listeners
}, [
h('router-view', data)
])
return nuxt._childVnode
}
}

View File

@ -29,7 +29,11 @@ export default {
if (typeof this.nuxtChildKey !== 'undefined' || this.$route.matched.length > 1) {
return this.nuxtChildKey || compile(this.$route.matched[0].path)(this.$route.params)
}
return this.$route.fullPath.split('#')[0]
const Component = this.$route.matched[0] && this.$route.matched[0].components.default
if (Component && Component.options && Component.options.key) {
return (typeof Component.options.key === 'function' ? Component.options.key(this.$route) : Component.options.key)
}
return this.$route.path
}
},
components: {

View File

@ -10,8 +10,11 @@ import Nuxt from './components/nuxt.js'
import App from '<%= appPath %>'
import { setContext, getLocation } from './utils'
<% if (store) { %>import { createStore } from './store.js'<% } %>
<% plugins.forEach(plugin => { %>import <%= plugin.name %> from '<%= plugin.name %>'
<% }) %>
/* Plugins */
<% plugins.forEach(plugin => { %>// <%= plugin.src %><%= (plugin.ssr===false) ? ' (Only included in client bundle)' : '' %>
import <%= plugin.name %> from '<%= plugin.name %>'<% }) %>
// Component: <no-ssr>
Vue.component(NoSSR.name, NoSSR)

View File

@ -60,6 +60,8 @@ export function createRouter () {
routes: [
<%= _routes %>
],
<% if (router.parseQuery) { %>parseQuery: <%= serialize(router.parseQuery).replace('parseQuery(', 'function(') %>,<% } %>
<% if (router.stringifyQuery) { %>stringifyQuery: <%= serialize(router.stringifyQuery).replace('stringifyQuery(', 'function(') %>,<% } %>
fallback: <%= router.fallback %>
})
}

View File

@ -70,7 +70,7 @@ export default async ssrContext => {
const renderErrorPage = async () => {
// Load layout for error page
let errLayout = (typeof NuxtError.layout === 'function' ? NuxtError.layout(app.context) : NuxtError.layout)
ssrContext.nuxt.layout = errLayout || ''
ssrContext.nuxt.layout = errLayout || 'default'
await _app.loadLayout(errLayout)
_app.setLayout(errLayout)
await beforeRender()
@ -91,7 +91,12 @@ export default async ssrContext => {
** Dispatch store nuxtServerInit
*/
if (store._actions && store._actions.nuxtServerInit) {
await store.dispatch('nuxtServerInit', app.context)
try {
await store.dispatch('nuxtServerInit', app.context)
} catch (err) {
debug('error occurred when calling nuxtServerInit: ', err.message)
throw err
}
}
// ...If there is a redirect or an error, stop the process
if (ssrContext.redirected) return noopApp()

View File

@ -65,48 +65,6 @@ export function getMatchedComponentsInstances(route) {
}))
}
function getRouteRecordWithParamNames (route) {
return route.matched.map(m => {
var paramNames = m.path.match(new RegExp(':[^\\/\\?]+', 'g'))
if (paramNames !== null) {
paramNames = paramNames.map(function (name) {
return name.substring(1)
})
}
return {
routeRecord: m,
paramNames: paramNames
}
})
}
export function getChangedComponentsInstances (to, from) {
var records = getRouteRecordWithParamNames(to)
var r = []
var parentChange = false
for (var i = 0; i < records.length; i++ ) {
var paramNames = records[i].paramNames
var instances = records[i].routeRecord.instances
instances = Object.keys(instances).map(function (key) {
return instances[key]
})
if (parentChange) {
r = [].concat(r, instances)
} else if (paramNames !== null) {
for (var pi in paramNames) {
var name = paramNames[pi]
if (to.params[name] !== from.params[name]) {
parentChange = true
r = [].concat(r, instances)
break
}
}
}
}
return r
}
export function flatMapComponents(route, fn) {
return Array.prototype.concat.apply([], route.matched.map(function (m, index) {
return Object.keys(m.components).map(function (key) {
@ -116,7 +74,7 @@ export function flatMapComponents(route, fn) {
}
export async function resolveRouteComponents(route) {
await Promise.all(
return await Promise.all(
flatMapComponents(route, async (Component, _, match, key) => {
// If component is a function, resolve it
if (typeof Component === 'function' && !Component.options) {
@ -255,6 +213,17 @@ export function compile(str, options) {
return tokensToFunction(parse(str, options))
}
export function getQueryDiff(toQuery, fromQuery) {
const diff = {}
const queries = { ...toQuery, ...fromQuery }
for (const k in queries) {
if (String(toQuery[k]) !== String(fromQuery[k])) {
diff[k] = true
}
}
return diff
}
/**
* The main path matching regexp utility.
*

View File

@ -1,6 +1,6 @@
import _ from 'lodash'
import chokidar from 'chokidar'
import fs, { remove, readFile, writeFile, mkdirp, utimes, existsSync } from 'fs-extra'
import fs, { remove, readFile, writeFile, mkdirp, existsSync } from 'fs-extra'
import hash from 'hash-sum'
import pify from 'pify'
import webpack from 'webpack'
@ -30,7 +30,7 @@ export default class Builder {
this.options = nuxt.options
// Fields that set on build
this.compiler = null
this.compilers = []
this.webpackDevMiddleware = null
this.webpackHotMiddleware = null
@ -63,7 +63,7 @@ export default class Builder {
return {
src: this.nuxt.resolvePath(p.src),
ssr: (p.ssr !== false),
name: basename(p.src, extname(p.src)).replace(/[^a-zA-Z?\d\s:]/g, '')
name: basename(p.src, extname(p.src)).replace(/[^a-zA-Z?\d\s:]/g, '') + '_plugin_' + hash(p.src)
}
})
}
@ -366,9 +366,6 @@ export default class Builder {
await mkdirp(dirname(path))
// Write file
await writeFile(path, content, 'utf8')
// Fix webpack loop (https://github.com/webpack/watchpack/issues/25#issuecomment-287789288)
const dateFS = Date.now() / 1000 - 1000
return utimes(path, dateFS, dateFS)
}))
}
@ -408,23 +405,19 @@ export default class Builder {
compilersOptions.push(dllWebpackConfig.call(this, clientConfig))
}
// Simulate webpack multi compiler interface
// Separate compilers are simpler, safer and faster
this.compilers = []
// Initialize shared FS and Cache
const sharedFS = this.options.dev && new MFS()
const sharedCache = {}
// Initialize compilers
compilersOptions.forEach(compilersOption => {
this.compilers = compilersOptions.map(compilersOption => {
const compiler = webpack(compilersOption)
// In dev, write files in memory FS (except for DLL)
if (sharedFS && !compiler.name.includes('-dll')) {
compiler.outputFileSystem = sharedFS
}
compiler.cache = sharedCache
this.compilers.push(compiler)
return compiler
})
// Start Builds

View File

@ -67,6 +67,7 @@ export default class Generator {
await Promise.all(routes.splice(0, this.options.generate.concurrency).map(async ({ route, payload }) => {
await waitFor(n++ * this.options.generate.interval)
await this.generateRoute({ route, payload, errors })
await this.nuxt.callHook('generate:routeCreated', route)
}))
}

View File

@ -3,6 +3,7 @@ import { cloneDeep } from 'lodash'
import { join, resolve } from 'path'
import webpack from 'webpack'
import { isUrl, urlJoin } from 'utils'
import TimeFixPlugin from './timefix-plugin'
/*
|--------------------------------------------------------------------------
@ -104,11 +105,17 @@ export default function webpackBaseConfig(name) {
plugins: this.options.build.plugins
}
// Add timefix-plugin before others plugins
config.plugins.unshift(new TimeFixPlugin())
// CSS extraction
if (this.options.build.extractCSS) {
config.plugins.push(new ExtractTextPlugin({
filename: this.options.build.filenames.css
}))
const extractCSS = this.options.build.extractCSS
if (extractCSS) {
const extractOptions = Object.assign(
{ filename: this.options.build.filenames.css },
typeof extractCSS === 'object' ? extractCSS : {}
)
config.plugins.push(new ExtractTextPlugin(extractOptions))
}
// Workaround for hiding Warnings about plugins without a default export (#1179)

View File

@ -27,52 +27,12 @@ debug.color = 2 // Force green color
export default function webpackClientConfig() {
let config = base.call(this, 'client')
// App entry
// Entry points
config.entry.app = resolve(this.options.buildDir, 'client.js')
config.entry.common = this.vendor()
config.entry.vendor = this.vendor()
// Extract vendor chunks for better caching
const _this = this
const totalPages = _this.routes ? _this.routes.length : 0
// This well-known vendor may exist as a dependency of other requests.
const maybeVendor = [
'/core-js/',
'/regenerator-runtime/',
'/es6-promise/',
'/babel-runtime/',
'/lodash/'
]
config.plugins.push(
new webpack.optimize.CommonsChunkPlugin({
name: 'common',
filename: this.options.build.filenames.vendor,
minChunks(module, count) {
// In the dev we use on-demand-entries.
// So, it makes no sense to use commonChunks based on the minChunks count.
// Instead, we move all the code in node_modules into each of the pages.
if (_this.options.dev) {
return false
}
// Detect and externalize well-known vendor if detected
if (module.context && maybeVendor.some(v => module.context.includes(v))) {
return true
}
// A module is extracted into the vendor chunk when...
return (
// If it's inside node_modules
/node_modules/.test(module.context) &&
// Do not externalize if the request is a CSS file
!/\.(css|less|scss|sass|styl|stylus)$/.test(module.request) &&
// Used in at-least 1/2 of the total pages
(totalPages <= 2 ? count >= totalPages : count >= totalPages * 0.5)
)
}
})
)
// Add CommonChunks plugin
commonChunksPlugin.call(this, config)
// Env object defined in nuxt.config.js
let env = {}
@ -80,12 +40,6 @@ export default function webpackClientConfig() {
env['process.env.' + key] = (['boolean', 'number'].indexOf(typeof value) !== -1 ? value : JSON.stringify(value))
})
// Webpack common plugins
/* istanbul ignore if */
if (!Array.isArray(config.plugins)) {
config.plugins = []
}
// Generate output HTML for SPA
config.plugins.push(
new HTMLPlugin({
@ -163,26 +117,8 @@ export default function webpackClientConfig() {
)
// DllReferencePlugin
// https://github.com/webpack/webpack/tree/master/examples/dll-user
if (this.options.build.dll) {
const _dlls = []
const vendorEntries = this.vendorEntries()
const dllDir = resolve(this.options.cacheDir, config.name + '-dll')
Object.keys(vendorEntries).forEach(v => {
const dllManifestFile = resolve(dllDir, v + '-manifest.json')
if (existsSync(dllManifestFile)) {
_dlls.push(v)
config.plugins.push(
new webpack.DllReferencePlugin({
// context: this.options.rootDir,
manifest: dllManifestFile // Using full path to allow finding .js dll file
})
)
}
})
if (_dlls.length) {
debug('Using dll for ' + _dlls.join(','))
}
dllPlugin.call(this, config)
}
}
@ -191,9 +127,9 @@ export default function webpackClientConfig() {
// --------------------------------------
if (!this.options.dev) {
// Scope Hoisting
config.plugins.push(
// new webpack.optimize.ModuleConcatenationPlugin()
)
if (this.options.build.scopeHoisting === true) {
config.plugins.push(new webpack.optimize.ModuleConcatenationPlugin())
}
// https://webpack.js.org/plugins/hashed-module-ids-plugin
config.plugins.push(new webpack.HashedModuleIdsPlugin())
@ -212,9 +148,7 @@ export default function webpackClientConfig() {
// Webpack Bundle Analyzer
if (this.options.build.analyze) {
config.plugins.push(
new BundleAnalyzerPlugin(Object.assign({}, this.options.build.analyze))
)
config.plugins.push(new BundleAnalyzerPlugin(Object.assign({}, this.options.build.analyze)))
}
}
@ -237,3 +171,68 @@ export default function webpackClientConfig() {
return config
}
// --------------------------------------------------------------------------
// Adds Common Chunks Plugin
// --------------------------------------------------------------------------
function commonChunksPlugin(config) {
const _this = this
const totalPages = _this.routes ? _this.routes.length : 0
// This well-known vendor may exist as a dependency of other requests.
const maybeVendor = [
'/core-js/',
'/regenerator-runtime/',
'/es6-promise/',
'/babel-runtime/',
'/lodash/'
]
// Create explicit vendor chunk
config.plugins.unshift(
new webpack.optimize.CommonsChunkPlugin({
name: 'vendor',
filename: this.options.build.filenames.vendor,
minChunks(module, count) {
// Detect and externalize well-known vendor if detected
if (module.context && maybeVendor.some(v => module.context.includes(v))) {
return true
}
// A module is extracted into the vendor chunk when...
return (
// If it's inside node_modules
/node_modules/.test(module.context) &&
// Do not externalize if the request is a CSS file
!/\.(css|less|scss|sass|styl|stylus)$/.test(module.request) &&
// Used in at-least 1/2 of the total pages
(totalPages <= 2 ? count >= totalPages : count >= totalPages * 0.5)
)
}
})
)
}
// --------------------------------------------------------------------------
// Adds DLL plugin
// https://github.com/webpack/webpack/tree/master/examples/dll-user
// --------------------------------------------------------------------------
function dllPlugin(config) {
const _dlls = []
const vendorEntries = this.vendorEntries()
const dllDir = resolve(this.options.cacheDir, config.name + '-dll')
Object.keys(vendorEntries).forEach(v => {
const dllManifestFile = resolve(dllDir, v + '-manifest.json')
if (existsSync(dllManifestFile)) {
_dlls.push(v)
config.plugins.push(
new webpack.DllReferencePlugin({
// context: this.options.rootDir,
manifest: dllManifestFile // Using full path to allow finding .js dll file
})
)
}
})
if (_dlls.length) {
debug('Using dll for ' + _dlls.join(','))
}
}

View File

@ -0,0 +1,18 @@
// Taken from https://github.com/egoist/poi/blob/3e93c88c520db2d20c25647415e6ae0d3de61145/packages/poi/lib/webpack/timefix-plugin.js#L1-L16
// Thanks to @egoist
export default class TimeFixPlugin {
constructor(timefix = 11000) {
this.timefix = timefix
}
apply(compiler) {
compiler.plugin('watch-run', (watching, callback) => {
watching.startTime += this.timefix
callback()
})
compiler.plugin('done', stats => {
stats.startTime -= this.timefix
})
}
}

View File

@ -2,7 +2,7 @@ export default function vueLoader() {
// https://vue-loader.vuejs.org/en
const config = {
postcss: this.options.build.postcss,
extractCSS: this.options.build.extractCSS,
extractCSS: !!this.options.build.extractCSS,
cssSourceMap: this.options.build.cssSourceMap,
preserveWhitespace: false,
loaders: {
@ -23,7 +23,9 @@ export default function vueLoader() {
},
transformToRequire: {
video: 'src',
source: 'src'
source: 'src',
object: 'src',
embed: 'src'
}
}

View File

@ -109,7 +109,9 @@ Options.from = function (_options) {
}
}
} else {
debug('Using PostCSS config from `build.postcss`')
if (Object.keys(options.build.postcss).length) {
debug('Using PostCSS config from `build.postcss`')
}
// Normalize & Apply default plugins
if (Array.isArray(options.build.postcss)) {
options.build.postcss = { plugins: options.build.postcss }
@ -147,7 +149,7 @@ Options.from = function (_options) {
_.defaultsDeep(options, modePreset)
// If no server-side rendering, add appear true transition
if (options.render.ssr === false) {
if (options.render.ssr === false && options.transition) {
options.transition.appear = true
}
@ -183,14 +185,15 @@ Options.defaults = {
build: {
analyze: false,
dll: false,
scopeHoisting: false,
extractCSS: false,
cssSourceMap: undefined,
ssr: undefined,
publicPath: '/_nuxt/',
filenames: {
css: 'common.[contenthash].css',
css: 'vendor.[contenthash].css',
manifest: 'manifest.[hash].js',
vendor: 'common.[chunkhash].js',
vendor: 'vendor.[chunkhash].js',
app: 'app.[chunkhash].js',
chunk: '[name].[chunkhash].js'
},
@ -272,6 +275,8 @@ Options.defaults = {
linkExactActiveClass: 'nuxt-link-exact-active',
extendRoutes: null,
scrollBehavior: null,
parseQuery: false,
stringifyQuery: false,
fallback: false
},
render: {

View File

@ -45,7 +45,8 @@ export default class MetaRenderer {
meta = {
HTML_ATTRS: '',
BODY_ATTRS: '',
HEAD: ''
HEAD: '',
BODY_SCRIPTS: ''
}
// Get vue-meta context
const m = await this.getMeta(url)
@ -55,6 +56,8 @@ export default class MetaRenderer {
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()
// BODY_SCRIPTS
meta.BODY_SCRIPTS = m.script.text({ body: true })
// Resources Hints
meta.resourceHints = ''
// Resource Hints

View File

@ -58,6 +58,26 @@ export default class Nuxt {
return this
}
plugin(name, fn) {
// eslint-disable-next-line no-console
console.error(`[warn] nuxt.plugin('${name}',..) is deprecated. Please use new hooks system.`)
// A tiny backward compatibility util
const hookMap = {
'ready': 'ready',
'close': 'close',
'listen': 'listen',
'built': 'build:done'
}
if (hookMap[name]) {
this.hook(hookMap[name], fn)
}
// Always return nuxt class which has plugin() for two level hooks
return this
}
hook(name, fn) {
if (!name || typeof fn !== 'function') {
return

View File

@ -488,8 +488,8 @@ export default class Renderer {
const ENV = this.options.env
if (this.noSSR || spa) {
const { HTML_ATTRS, BODY_ATTRS, HEAD, resourceHints } = await this.metaRenderer.render(context)
const APP = `<div id="__nuxt">${this.resources.loadingHTML}</div>`
const { HTML_ATTRS, BODY_ATTRS, HEAD, BODY_SCRIPTS, resourceHints } = await this.metaRenderer.render(context)
const APP = `<div id="__nuxt">${this.resources.loadingHTML}</div>` + BODY_SCRIPTS
// Detect 404 errors
if (url.includes(this.options.build.publicPath) || url.includes('__webpack')) {
@ -528,6 +528,7 @@ export default class Renderer {
}
APP += `<script type="text/javascript">window.__NUXT__=${serialize(context.nuxt, { isJSON: true })};</script>`
APP += context.renderScripts()
APP += m.script.text({ body: true })
HEAD += context.renderStyles()

View File

@ -70,6 +70,7 @@
"babel-core": "^6.26.0",
"babel-loader": "^7.1.2",
"babel-preset-vue-app": "^1.3.1",
"caniuse-lite": "^1.0.30000758",
"chalk": "^2.3.0",
"chokidar": "^1.7.0",
"clone": "^2.1.1",
@ -95,7 +96,7 @@
"open-in-editor": "^2.2.0",
"opencollective": "^1.0.3",
"pify": "^3.0.0",
"postcss": "^6.0.13",
"postcss": "^6.0.14",
"postcss-cssnext": "^3.0.2",
"postcss-import": "^11.0.0",
"postcss-loader": "^2.0.8",
@ -109,12 +110,12 @@
"source-map-support": "^0.5.0",
"uglifyjs-webpack-plugin": "^1.0.1",
"url-loader": "^0.6.2",
"vue": "^2.5.2",
"vue-loader": "^13.3.0",
"vue-meta": "^1.2.0",
"vue": "^2.5.3",
"vue-loader": "^13.4.0",
"vue-meta": "^1.3.1",
"vue-router": "^3.0.1",
"vue-server-renderer": "^2.5.2",
"vue-template-compiler": "^2.5.2",
"vue-server-renderer": "^2.5.3",
"vue-template-compiler": "^2.5.3",
"vuex": "^3.0.1",
"webpack": "^3.8.1",
"webpack-bundle-analyzer": "^2.9.0",
@ -155,7 +156,7 @@
"rollup-plugin-replace": "^2.0.0",
"rollup-watch": "^4.3.1",
"std-mocks": "^1.0.1",
"uglify-js": "^3.1.6"
"uglify-js": "^3.1.7"
},
"collective": {
"type": "opencollective",

View File

@ -50,8 +50,8 @@
"pretty-error": "^2.1.1",
"minimist": "^1.2.0",
"lodash": "^4.17.4",
"hash-sum": "^1.0.2",
"debug": "^3.1.0",
"hash-sum": "^1.0.2",
"chalk": "^2.3.0",
"ansi-html": "^0.0.7",
"serialize-javascript": "^1.4.0",
@ -60,12 +60,12 @@
"serve-static": "^1.13.1",
"compression": "^1.7.1",
"fs-extra": "^4.0.2",
"vue-server-renderer": "^2.5.2",
"vue-server-renderer": "^2.5.3",
"@nuxtjs/youch": "^3.1.0",
"source-map": "^0.6.1",
"connect": "^3.6.5",
"vue": "^2.5.2",
"vue-meta": "^1.2.0",
"vue": "^2.5.3",
"vue-meta": "^1.3.1",
"lru-cache": "^4.1.1",
"server-destroy": "^1.0.1",
"open-in-editor": "^2.2.0"

View File

@ -40,69 +40,71 @@ test('Open /', async t => {
})
test('/stateless', async t => {
await page.nuxt.navigate('/stateless')
const { hook } = await page.nuxt.navigate('/stateless', false)
const loading = await page.nuxt.loadingData()
t.is(loading.show, true)
await page.nuxt.waitForNavigation()
await hook
t.is(await page.$text('h1'), 'My component!')
})
test('/css', async t => {
await page.nuxt.navigate('/css', true)
await page.nuxt.navigate('/css')
t.is(await page.$text('.red'), 'This is red')
t.is(await page.$eval('.red', (red) => window.getComputedStyle(red).color), 'rgb(255, 0, 0)')
})
test('/stateful', async t => {
await page.nuxt.navigate('/stateful', true)
await page.nuxt.navigate('/stateful')
t.is(await page.$text('p'), 'The answer is 42')
})
test('/store', async t => {
await page.nuxt.navigate('/store', true)
await page.nuxt.navigate('/store')
t.is(await page.$text('h1'), 'Vuex Nested Modules')
t.is(await page.$text('p'), '1')
})
test('/head', async t => {
await page.nuxt.navigate('/head', true)
const msg = new Promise((resolve) => page.on('console', (msg) => resolve(msg.text)))
await page.nuxt.navigate('/head')
const metas = await page.$$attr('meta', 'content')
t.is(await msg, 'Body script!')
t.is(await page.title(), 'My title - Nuxt.js')
t.is(await page.$text('h1'), 'I can haz meta tags')
t.is(metas[0], 'my meta')
})
test('/async-data', async t => {
await page.nuxt.navigate('/async-data', true)
await page.nuxt.navigate('/async-data')
t.is(await page.$text('p'), 'Nuxt.js')
})
test('/await-async-data', async t => {
await page.nuxt.navigate('/await-async-data', true)
await page.nuxt.navigate('/await-async-data')
t.is(await page.$text('p'), 'Await Nuxt.js')
})
test('/callback-async-data', async t => {
await page.nuxt.navigate('/callback-async-data', true)
await page.nuxt.navigate('/callback-async-data')
t.is(await page.$text('p'), 'Callback Nuxt.js')
})
test('/users/1', async t => {
await page.nuxt.navigate('/users/1', true)
await page.nuxt.navigate('/users/1')
t.is(await page.$text('h1'), 'User: 1')
})
test('/validate should display a 404', async t => {
await page.nuxt.navigate('/validate', true)
await page.nuxt.navigate('/validate')
const error = await page.nuxt.errorData()
t.is(error.statusCode, 404)
@ -110,59 +112,59 @@ test('/validate should display a 404', async t => {
})
test('/validate?valid=true', async t => {
await page.nuxt.navigate('/validate?valid=true', true)
await page.nuxt.navigate('/validate?valid=true')
t.is(await page.$text('h1'), 'I am valid')
})
test('/redirect', async t => {
await page.nuxt.navigate('/redirect', true)
await page.nuxt.navigate('/redirect')
t.is(await page.$text('h1'), 'Index page')
})
test('/error', async t => {
await page.nuxt.navigate('/error', true)
await page.nuxt.navigate('/error')
t.deepEqual(await page.nuxt.errorData(), { statusCode: 500 })
t.is(await page.$text('.title'), 'Error mouahahah')
})
test('/error2', async t => {
await page.nuxt.navigate('/error2', true)
await page.nuxt.navigate('/error2')
t.is(await page.$text('.title'), 'Custom error')
t.deepEqual(await page.nuxt.errorData(), { message: 'Custom error' })
})
test('/redirect2', async t => {
await page.nuxt.navigate('/redirect2', true)
await page.nuxt.navigate('/redirect2')
t.is(await page.$text('h1'), 'Index page')
})
test('/no-ssr', async t => {
await page.nuxt.navigate('/no-ssr', true)
await page.nuxt.navigate('/no-ssr')
t.is(await page.$text('h1'), 'Displayed only on client-side')
})
test('/meta', async t => {
await page.nuxt.navigate('/meta', true)
await page.nuxt.navigate('/meta')
const state = await page.nuxt.storeState()
t.deepEqual(state.meta, [{ works: true }])
})
test('/fn-midd', async t => {
await page.nuxt.navigate('/fn-midd', true)
await page.nuxt.navigate('/fn-midd')
t.is(await page.$text('.title'), 'You need to ask the permission')
t.deepEqual(await page.nuxt.errorData(), { message: 'You need to ask the permission', statusCode: 403 })
})
test('/fn-midd?please=true', async t => {
await page.nuxt.navigate('/fn-midd?please=true', true)
await page.nuxt.navigate('/fn-midd?please=true')
const h1 = await page.$text('h1')
t.true(h1.includes('Date:'))

View File

@ -55,12 +55,17 @@ test('/store', async t => {
})
test('/head', async t => {
stdMocks.use()
const window = await nuxt.renderAndGetWindow(url('/head'), { virtualConsole: false })
const html = window.document.body.innerHTML
const metas = window.document.getElementsByTagName('meta')
stdMocks.restore()
const { stdout } = stdMocks.flush()
t.is(stdout[0], 'Body script!\n')
t.is(window.document.title, 'My title - Nuxt.js')
t.is(metas[0].getAttribute('content'), 'my meta')
t.true(html.includes('<div><h1>I can haz meta tags</h1></div>'))
t.true(html.includes('<script data-n-head="true" src="/body.js" data-body="true">'))
})
test('/async-data', async t => {

View File

@ -40,10 +40,10 @@ test('Loading /patch and keep ', async t => {
})
test('Navigate to /patch/1', async t => {
await page.nuxt.navigate('/patch/1')
const { hook } = await page.nuxt.navigate('/patch/1', false)
const loading = await page.nuxt.loadingData()
t.is(loading.show, true)
await page.nuxt.waitForNavigation()
await hook
const h2 = await page.$text('h2')
t.true(h2.includes('_id:'))
@ -53,7 +53,7 @@ test('Navigate to /patch/1', async t => {
})
test('Navigate to /patch/2', async t => {
await page.nuxt.navigate('/patch/2', true)
await page.nuxt.navigate('/patch/2')
const date = await page.$text('[data-date-id]')
t.is(await page.$text('h3'), 'Index')
@ -63,28 +63,19 @@ test('Navigate to /patch/2', async t => {
})
test('Navigate to /patch/2?test=true', async t => {
await page.nuxt.navigate('/patch/2?test=true', true)
await page.nuxt.navigate('/patch/2?test=true')
t.is(dates.patch, await page.$text('[data-date-patch]'))
t.is(dates.id, await page.$text('[data-date-id]'))
})
test('Navigate to /patch/2#test', async t => {
await page.nuxt.navigate('/patch/2#test', true)
await page.nuxt.navigate('/patch/2#test')
t.is(dates.patch, await page.$text('[data-date-patch]'))
t.is(dates.id, await page.$text('[data-date-id]'))
})
test('Navigate to /patch/2/child', async t => {
await page.nuxt.navigate('/patch/2/child', true)
dates.child = await page.$text('[data-date-child]')
t.is(dates.patch, await page.$text('[data-date-patch]'))
t.is(dates.id, await page.$text('[data-date-id]'))
t.true(+dates.child > +dates.id)
})
test('Navigate to /patch/2/child', async t => {
await page.nuxt.navigate('/patch/2/child', true)
await page.nuxt.navigate('/patch/2/child')
dates.child = await page.$text('[data-date-child]')
dates.slug = await page.$text('[data-date-child-slug]')
@ -95,7 +86,7 @@ test('Navigate to /patch/2/child', async t => {
})
test('Navigate to /patch/2/child/1', async t => {
await page.nuxt.navigate('/patch/2/child/1', true)
await page.nuxt.navigate('/patch/2/child/1')
const date = await page.$text('[data-date-child-slug]')
t.is(dates.patch, await page.$text('[data-date-patch]'))
@ -106,7 +97,7 @@ test('Navigate to /patch/2/child/1', async t => {
})
test('Navigate to /patch/2/child/1?foo=bar', async t => {
await page.nuxt.navigate('/patch/2/child/1?foo=bar', true)
await page.nuxt.navigate('/patch/2/child/1?foo=bar')
t.is(dates.patch, await page.$text('[data-date-patch]'))
t.is(dates.id, await page.$text('[data-date-id]'))

View File

@ -14,5 +14,6 @@ module.exports = {
},
bad: null,
'': true
}
},
transition: false
}

View File

@ -10,6 +10,9 @@ export default {
title: 'My title',
meta: [
{ content: 'my meta' }
],
script: [
{ src: '/body.js', body: true }
]
}
}

2
test/fixtures/basic/static/body.js vendored Normal file
View File

@ -0,0 +1,2 @@
/* eslint-disable no-console */
console.log('Body script!')

View File

@ -1,5 +1,6 @@
module.exports = {
rootDir: __dirname,
mode: 'spa',
dev: false
dev: false,
transition: false
}

View File

@ -27,11 +27,14 @@ export async function page(url) {
page.$nuxt = await page.evaluateHandle('window.$nuxt')
page.nuxt = {
async navigate(path, wait = false) {
async navigate(path, waitEnd = true) {
const hook = page.evaluate(() => {
return new Promise((resolve) => window.$nuxt.$once('routeChanged', resolve))
.then(() => new Promise((resolve) => setTimeout(resolve, 50)))
})
await page.evaluate(($nuxt, path) => $nuxt.$router.push(path), page.$nuxt, path)
if (wait) {
await this.waitForNavigation()
}
if (waitEnd) await hook
return { hook }
},
routeData() {
return page.evaluate(($nuxt) => {
@ -49,9 +52,6 @@ export async function page(url) {
},
storeState() {
return page.evaluate(($nuxt) => $nuxt.$store.state, page.$nuxt)
},
waitForNavigation() {
return page.waitForFunction('window.$nuxt.$loading.$data.show === false')
}
}
return page

View File

@ -8,8 +8,9 @@ const url = (route) => 'http://localhost:' + port + route
const renderRoute = async _url => {
const window = await nuxt.renderAndGetWindow(url(_url))
const head = window.document.head.innerHTML
const html = window.document.body.innerHTML
return { window, html }
return { window, head, html }
}
// Init nuxt.js and create server listening on localhost:4000
@ -29,6 +30,11 @@ test('/custom (custom layout)', async t => {
t.true(html.includes('Custom layout'))
})
test('/custom (not default layout)', async t => {
const { head } = await renderRoute('/custom')
t.false(head.includes('src="/_nuxt/layouts/default.'))
})
// Close server and ask nuxt to stop listening to file changes
test.after('Closing server and nuxt.js', t => {
nuxt.close()

View File

@ -42,7 +42,7 @@ test('/ (custom app.html)', async t => {
test('/ (custom build.publicPath)', async t => {
const { html } = await nuxt.renderRoute('/')
t.true(html.includes('src="/test/orion/common.'))
t.true(html.includes('src="/test/orion/vendor.'))
})
test('/test/ (router base)', async t => {

380
yarn.lock
View File

@ -38,6 +38,59 @@
imurmurhash "^0.1.4"
slide "^1.1.5"
"@babel/code-frame@7.0.0-beta.31", "@babel/code-frame@^7.0.0-beta.31":
version "7.0.0-beta.31"
resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.0.0-beta.31.tgz#473d021ecc573a2cce1c07d5b509d5215f46ba35"
dependencies:
chalk "^2.0.0"
esutils "^2.0.2"
js-tokens "^3.0.0"
"@babel/helper-function-name@7.0.0-beta.31":
version "7.0.0-beta.31"
resolved "https://registry.yarnpkg.com/@babel/helper-function-name/-/helper-function-name-7.0.0-beta.31.tgz#afe63ad799209989348b1109b44feb66aa245f57"
dependencies:
"@babel/helper-get-function-arity" "7.0.0-beta.31"
"@babel/template" "7.0.0-beta.31"
"@babel/traverse" "7.0.0-beta.31"
"@babel/types" "7.0.0-beta.31"
"@babel/helper-get-function-arity@7.0.0-beta.31":
version "7.0.0-beta.31"
resolved "https://registry.yarnpkg.com/@babel/helper-get-function-arity/-/helper-get-function-arity-7.0.0-beta.31.tgz#1176d79252741218e0aec872ada07efb2b37a493"
dependencies:
"@babel/types" "7.0.0-beta.31"
"@babel/template@7.0.0-beta.31":
version "7.0.0-beta.31"
resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.0.0-beta.31.tgz#577bb29389f6c497c3e7d014617e7d6713f68bda"
dependencies:
"@babel/code-frame" "7.0.0-beta.31"
"@babel/types" "7.0.0-beta.31"
babylon "7.0.0-beta.31"
lodash "^4.2.0"
"@babel/traverse@7.0.0-beta.31", "@babel/traverse@^7.0.0-beta.31":
version "7.0.0-beta.31"
resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.0.0-beta.31.tgz#db399499ad74aefda014f0c10321ab255134b1df"
dependencies:
"@babel/code-frame" "7.0.0-beta.31"
"@babel/helper-function-name" "7.0.0-beta.31"
"@babel/types" "7.0.0-beta.31"
babylon "7.0.0-beta.31"
debug "^3.0.1"
globals "^10.0.0"
invariant "^2.2.0"
lodash "^4.2.0"
"@babel/types@7.0.0-beta.31", "@babel/types@^7.0.0-beta.31":
version "7.0.0-beta.31"
resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.0.0-beta.31.tgz#42c9c86784f674c173fb21882ca9643334029de4"
dependencies:
esutils "^2.0.2"
lodash "^4.2.0"
to-fast-properties "^2.0.0"
"@concordance/react@^1.0.0":
version "1.0.0"
resolved "https://registry.yarnpkg.com/@concordance/react/-/react-1.0.0.tgz#fcf3cad020e5121bfd1c61d05bc3516aac25f734"
@ -52,9 +105,9 @@
mustache "^2.3.0"
stack-trace "0.0.10"
"@types/node@^6.0.46":
version "6.0.90"
resolved "https://registry.yarnpkg.com/@types/node/-/node-6.0.90.tgz#0ed74833fa1b73dcdb9409dcb1c97ec0a8b13b02"
"@types/node@*":
version "8.0.49"
resolved "https://registry.yarnpkg.com/@types/node/-/node-8.0.49.tgz#417f86ab4829c629fe561779ee48751e0fe2a11b"
abab@^1.0.3:
version "1.0.4"
@ -97,11 +150,7 @@ acorn@^4.0.3:
version "4.0.13"
resolved "https://registry.yarnpkg.com/acorn/-/acorn-4.0.13.tgz#105495ae5361d697bd195c825192e1ad7f253787"
acorn@^5.0.0, acorn@^5.1.1, acorn@^5.1.2:
version "5.1.2"
resolved "https://registry.yarnpkg.com/acorn/-/acorn-5.1.2.tgz#911cb53e036807cf0fa778dc5d370fbd864246d7"
acorn@^5.2.1:
acorn@^5.0.0, acorn@^5.1.1, acorn@^5.1.2, acorn@^5.2.1:
version "5.2.1"
resolved "https://registry.yarnpkg.com/acorn/-/acorn-5.2.1.tgz#317ac7821826c22c702d66189ab8359675f135d7"
@ -112,8 +161,8 @@ agent-base@^4.1.0:
es6-promisify "^5.0.0"
ajv-keywords@^2.0.0, ajv-keywords@^2.1.0:
version "2.1.0"
resolved "https://registry.yarnpkg.com/ajv-keywords/-/ajv-keywords-2.1.0.tgz#a296e17f7bfae7c1ce4f7e0de53d29cb32162df0"
version "2.1.1"
resolved "https://registry.yarnpkg.com/ajv-keywords/-/ajv-keywords-2.1.1.tgz#617997fc5f60576894c435f940d819e135b80762"
ajv@^4.9.1:
version "4.11.8"
@ -161,6 +210,10 @@ ansi-escapes@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/ansi-escapes/-/ansi-escapes-2.0.0.tgz#5bae52be424878dd9783e8910e3fc2922e83c81b"
ansi-escapes@^3.0.0:
version "3.0.0"
resolved "https://registry.yarnpkg.com/ansi-escapes/-/ansi-escapes-3.0.0.tgz#ec3e8b4e9f8064fc02c3ac9b65f1c275bda8ef92"
ansi-html@0.0.7, ansi-html@^0.0.7:
version "0.0.7"
resolved "https://registry.yarnpkg.com/ansi-html/-/ansi-html-0.0.7.tgz#813584021962a9e9e6fd039f940d12f56ca7859e"
@ -274,8 +327,8 @@ arrify@^1.0.0, arrify@^1.0.1:
resolved "https://registry.yarnpkg.com/arrify/-/arrify-1.0.1.tgz#898508da2226f380df904728456849c1501a4b0d"
asn1.js@^4.0.0:
version "4.9.1"
resolved "https://registry.yarnpkg.com/asn1.js/-/asn1.js-4.9.1.tgz#48ba240b45a9280e94748990ba597d216617fd40"
version "4.9.2"
resolved "https://registry.yarnpkg.com/asn1.js/-/asn1.js-4.9.2.tgz#8117ef4f7ed87cd8f89044b5bff97ac243a16c9a"
dependencies:
bn.js "^4.0.0"
inherits "^2.0.1"
@ -312,8 +365,8 @@ async@^1.4.0:
resolved "https://registry.yarnpkg.com/async/-/async-1.5.2.tgz#ec6a61ae56480c0c3cb241c95618e20892f9672a"
async@^2.1.2, async@^2.4.1:
version "2.5.0"
resolved "https://registry.yarnpkg.com/async/-/async-2.5.0.tgz#843190fd6b7357a0b9e1c956edddd5ec8462b54d"
version "2.6.0"
resolved "https://registry.yarnpkg.com/async/-/async-2.6.0.tgz#61a29abb6fcc026fea77e56d1c6ec53a795951f4"
dependencies:
lodash "^4.14.0"
@ -454,14 +507,6 @@ aws4@^1.2.1, aws4@^1.6.0:
version "1.6.0"
resolved "https://registry.yarnpkg.com/aws4/-/aws4-1.6.0.tgz#83ef5ca860b2b32e4a0deedee8c771b9db57471e"
babel-code-frame@7.0.0-beta.0:
version "7.0.0-beta.0"
resolved "https://registry.yarnpkg.com/babel-code-frame/-/babel-code-frame-7.0.0-beta.0.tgz#418a7b5f3f7dc9a4670e61b1158b4c5661bec98d"
dependencies:
chalk "^2.0.0"
esutils "^2.0.2"
js-tokens "^3.0.0"
babel-code-frame@^6.11.0, babel-code-frame@^6.22.0, babel-code-frame@^6.26.0:
version "6.26.0"
resolved "https://registry.yarnpkg.com/babel-code-frame/-/babel-code-frame-6.26.0.tgz#63fd43f7dc1e3bb7ce35947db8fe369a3f58c74b"
@ -495,13 +540,13 @@ babel-core@^6.17.0, babel-core@^6.26.0:
source-map "^0.5.6"
babel-eslint@^8.0.1:
version "8.0.1"
resolved "https://registry.yarnpkg.com/babel-eslint/-/babel-eslint-8.0.1.tgz#5d718be7a328625d006022eb293ed3008cbd6346"
version "8.0.2"
resolved "https://registry.yarnpkg.com/babel-eslint/-/babel-eslint-8.0.2.tgz#e44fb9a037d749486071d52d65312f5c20aa7530"
dependencies:
babel-code-frame "7.0.0-beta.0"
babel-traverse "7.0.0-beta.0"
babel-types "7.0.0-beta.0"
babylon "7.0.0-beta.22"
"@babel/code-frame" "^7.0.0-beta.31"
"@babel/traverse" "^7.0.0-beta.31"
"@babel/types" "^7.0.0-beta.31"
babylon "^7.0.0-beta.31"
babel-generator@^6.1.0, babel-generator@^6.18.0, babel-generator@^6.26.0:
version "6.26.0"
@ -550,15 +595,6 @@ babel-helper-explode-assignable-expression@^6.24.1:
babel-traverse "^6.24.1"
babel-types "^6.24.1"
babel-helper-function-name@7.0.0-beta.0:
version "7.0.0-beta.0"
resolved "https://registry.yarnpkg.com/babel-helper-function-name/-/babel-helper-function-name-7.0.0-beta.0.tgz#d1b6779b647e5c5c31ebeb05e13b998e4d352d56"
dependencies:
babel-helper-get-function-arity "7.0.0-beta.0"
babel-template "7.0.0-beta.0"
babel-traverse "7.0.0-beta.0"
babel-types "7.0.0-beta.0"
babel-helper-function-name@^6.24.1:
version "6.24.1"
resolved "https://registry.yarnpkg.com/babel-helper-function-name/-/babel-helper-function-name-6.24.1.tgz#d3475b8c03ed98242a25b48351ab18399d3580a9"
@ -569,12 +605,6 @@ babel-helper-function-name@^6.24.1:
babel-traverse "^6.24.1"
babel-types "^6.24.1"
babel-helper-get-function-arity@7.0.0-beta.0:
version "7.0.0-beta.0"
resolved "https://registry.yarnpkg.com/babel-helper-get-function-arity/-/babel-helper-get-function-arity-7.0.0-beta.0.tgz#9d1ab7213bb5efe1ef1638a8ea1489969b5a8b6e"
dependencies:
babel-types "7.0.0-beta.0"
babel-helper-get-function-arity@^6.24.1:
version "6.24.1"
resolved "https://registry.yarnpkg.com/babel-helper-get-function-arity/-/babel-helper-get-function-arity-6.24.1.tgz#8f7782aa93407c41d3aa50908f89b031b1b6853d"
@ -644,10 +674,6 @@ babel-loader@^7.1.2:
loader-utils "^1.0.2"
mkdirp "^0.5.1"
babel-messages@7.0.0-beta.0:
version "7.0.0-beta.0"
resolved "https://registry.yarnpkg.com/babel-messages/-/babel-messages-7.0.0-beta.0.tgz#6df01296e49fc8fbd0637394326a167f36da817b"
babel-messages@^6.23.0:
version "6.23.0"
resolved "https://registry.yarnpkg.com/babel-messages/-/babel-messages-6.23.0.tgz#f3cdf4703858035b2a2951c6ec5edf6c62f2630e"
@ -1030,15 +1056,6 @@ babel-runtime@^6.18.0, babel-runtime@^6.20.0, babel-runtime@^6.22.0, babel-runti
core-js "^2.4.0"
regenerator-runtime "^0.11.0"
babel-template@7.0.0-beta.0:
version "7.0.0-beta.0"
resolved "https://registry.yarnpkg.com/babel-template/-/babel-template-7.0.0-beta.0.tgz#85083cf9e4395d5e48bf5154d7a8d6991cafecfb"
dependencies:
babel-traverse "7.0.0-beta.0"
babel-types "7.0.0-beta.0"
babylon "7.0.0-beta.22"
lodash "^4.2.0"
babel-template@^6.16.0, babel-template@^6.24.1, babel-template@^6.26.0:
version "6.26.0"
resolved "https://registry.yarnpkg.com/babel-template/-/babel-template-6.26.0.tgz#de03e2d16396b069f46dd9fff8521fb1a0e35e02"
@ -1049,20 +1066,6 @@ babel-template@^6.16.0, babel-template@^6.24.1, babel-template@^6.26.0:
babylon "^6.18.0"
lodash "^4.17.4"
babel-traverse@7.0.0-beta.0:
version "7.0.0-beta.0"
resolved "https://registry.yarnpkg.com/babel-traverse/-/babel-traverse-7.0.0-beta.0.tgz#da14be9b762f62a2f060db464eaafdd8cd072a41"
dependencies:
babel-code-frame "7.0.0-beta.0"
babel-helper-function-name "7.0.0-beta.0"
babel-messages "7.0.0-beta.0"
babel-types "7.0.0-beta.0"
babylon "7.0.0-beta.22"
debug "^3.0.1"
globals "^10.0.0"
invariant "^2.2.0"
lodash "^4.2.0"
babel-traverse@^6.18.0, babel-traverse@^6.24.1, babel-traverse@^6.26.0:
version "6.26.0"
resolved "https://registry.yarnpkg.com/babel-traverse/-/babel-traverse-6.26.0.tgz#46a9cbd7edcc62c8e5c064e2d2d8d0f4035766ee"
@ -1077,14 +1080,6 @@ babel-traverse@^6.18.0, babel-traverse@^6.24.1, babel-traverse@^6.26.0:
invariant "^2.2.2"
lodash "^4.17.4"
babel-types@7.0.0-beta.0:
version "7.0.0-beta.0"
resolved "https://registry.yarnpkg.com/babel-types/-/babel-types-7.0.0-beta.0.tgz#eb8b6e556470e6dcc4aef982d79ad229469b5169"
dependencies:
esutils "^2.0.2"
lodash "^4.2.0"
to-fast-properties "^2.0.0"
babel-types@^6.18.0, babel-types@^6.19.0, babel-types@^6.24.1, babel-types@^6.26.0:
version "6.26.0"
resolved "https://registry.yarnpkg.com/babel-types/-/babel-types-6.26.0.tgz#a3b073f94ab49eb6fa55cd65227a334380632497"
@ -1094,9 +1089,9 @@ babel-types@^6.18.0, babel-types@^6.19.0, babel-types@^6.24.1, babel-types@^6.26
lodash "^4.17.4"
to-fast-properties "^1.0.3"
babylon@7.0.0-beta.22:
version "7.0.0-beta.22"
resolved "https://registry.yarnpkg.com/babylon/-/babylon-7.0.0-beta.22.tgz#74f0ad82ed7c7c3cfeab74cf684f815104161b65"
babylon@7.0.0-beta.31, babylon@^7.0.0-beta.31:
version "7.0.0-beta.31"
resolved "https://registry.yarnpkg.com/babylon/-/babylon-7.0.0-beta.31.tgz#7ec10f81e0e456fd0f855ad60fa30c2ac454283f"
babylon@^6.1.0, babylon@^6.18.0:
version "6.18.0"
@ -1280,11 +1275,11 @@ browserslist@^1.3.6, browserslist@^1.5.2, browserslist@^1.7.6:
electron-to-chromium "^1.2.7"
browserslist@^2.0.0, browserslist@^2.1.2, browserslist@^2.5.1:
version "2.5.1"
resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-2.5.1.tgz#68e4bc536bbcc6086d62843a2ffccea8396821c6"
version "2.7.0"
resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-2.7.0.tgz#dc375dc70048fec3d989042a35022342902eff00"
dependencies:
caniuse-lite "^1.0.30000744"
electron-to-chromium "^1.3.24"
caniuse-lite "^1.0.30000757"
electron-to-chromium "^1.3.27"
buf-compare@^1.0.0:
version "1.0.1"
@ -1408,12 +1403,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.30000755"
resolved "https://registry.yarnpkg.com/caniuse-db/-/caniuse-db-1.0.30000755.tgz#a08c547c39dbe4ad07dcca9763fcbbff0c891de0"
version "1.0.30000758"
resolved "https://registry.yarnpkg.com/caniuse-db/-/caniuse-db-1.0.30000758.tgz#a235627b1922e878b63164942c991b84de92c810"
caniuse-lite@^1.0.0, caniuse-lite@^1.0.30000744, caniuse-lite@^1.0.30000748:
version "1.0.30000755"
resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30000755.tgz#9ce5f6e06bd75ec8209abe8853c3beef02248d65"
caniuse-lite@^1.0.0, caniuse-lite@^1.0.30000748, caniuse-lite@^1.0.30000757, caniuse-lite@^1.0.30000758:
version "1.0.30000758"
resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30000758.tgz#e261140076651049cf6891ed4bc649b5c8c26c69"
capture-stack-trace@^1.0.0:
version "1.0.0"
@ -1898,8 +1893,8 @@ cryptiles@3.x.x:
boom "5.x.x"
crypto-browserify@^3.11.0:
version "3.11.1"
resolved "https://registry.yarnpkg.com/crypto-browserify/-/crypto-browserify-3.11.1.tgz#948945efc6757a400d6e5e5af47194d10064279f"
version "3.12.0"
resolved "https://registry.yarnpkg.com/crypto-browserify/-/crypto-browserify-3.12.0.tgz#396cf9f3137f03e4b8e532c58f698254e00f80ec"
dependencies:
browserify-cipher "^1.0.0"
browserify-sign "^4.0.0"
@ -1911,12 +1906,13 @@ crypto-browserify@^3.11.0:
pbkdf2 "^3.0.3"
public-encrypt "^4.0.0"
randombytes "^2.0.0"
randomfill "^1.0.3"
crypto-random-string@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/crypto-random-string/-/crypto-random-string-1.0.0.tgz#a230f64f568310e1498009940790ec99545bca7e"
css-color-function@^1.3.0:
css-color-function@~1.3.3:
version "1.3.3"
resolved "https://registry.yarnpkg.com/css-color-function/-/css-color-function-1.3.3.tgz#8ed24c2c0205073339fafa004bc8c141fccb282e"
dependencies:
@ -2079,12 +2075,6 @@ debug-log@^1.0.1:
version "1.0.1"
resolved "https://registry.yarnpkg.com/debug-log/-/debug-log-1.0.1.tgz#2307632d4c04382b8df8a32f70b895046d52745f"
debug@2.2.0:
version "2.2.0"
resolved "https://registry.yarnpkg.com/debug/-/debug-2.2.0.tgz#f87057e995b1a1f6ae6a4960664137bc56f039da"
dependencies:
ms "0.7.1"
debug@2.6.9, debug@^2.2.0, debug@^2.4.1, debug@^2.6.8:
version "2.6.9"
resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.9.tgz#5d128515df134ff327e90a4c93f4e077a536341f"
@ -2113,9 +2103,9 @@ deep-is@~0.1.3:
version "0.1.3"
resolved "https://registry.yarnpkg.com/deep-is/-/deep-is-0.1.3.tgz#b369d6fb5dbc13eecf524f91b070feedc357cf34"
deepmerge@^1.5.0:
version "1.5.2"
resolved "https://registry.yarnpkg.com/deepmerge/-/deepmerge-1.5.2.tgz#10499d868844cdad4fee0842df8c7f6f0c95a753"
deepmerge@^2.0.0:
version "2.0.1"
resolved "https://registry.yarnpkg.com/deepmerge/-/deepmerge-2.0.1.tgz#25c1c24f110fb914f80001b925264dd77f3f4312"
default-require-extensions@^1.0.0:
version "1.0.0"
@ -2179,6 +2169,10 @@ detect-indent@^5.0.0:
version "5.0.0"
resolved "https://registry.yarnpkg.com/detect-indent/-/detect-indent-5.0.0.tgz#3871cc0a6a002e8c3e5b3cf7f336264675f06b9d"
detect-libc@^1.0.2:
version "1.0.2"
resolved "https://registry.yarnpkg.com/detect-libc/-/detect-libc-1.0.2.tgz#71ad5d204bf17a6a6ca8f450c61454066ef461e1"
diffie-hellman@^5.0.0:
version "5.0.2"
resolved "https://registry.yarnpkg.com/diffie-hellman/-/diffie-hellman-5.0.2.tgz#b5835739270cfe26acf632099fded2a07f209e5e"
@ -2299,7 +2293,7 @@ ejs@^2.5.6:
version "2.5.7"
resolved "https://registry.yarnpkg.com/ejs/-/ejs-2.5.7.tgz#cc872c168880ae3c7189762fd5ffc00896c9518a"
electron-to-chromium@^1.2.7, electron-to-chromium@^1.3.24:
electron-to-chromium@^1.2.7, electron-to-chromium@^1.3.27:
version "1.3.27"
resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.3.27.tgz#78ecb8a399066187bb374eede35d9c70565a803d"
@ -2729,7 +2723,7 @@ extend@~3.0.0, extend@~3.0.1:
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.1, external-editor@^2.0.4:
version "2.0.5"
resolved "https://registry.yarnpkg.com/external-editor/-/external-editor-2.0.5.tgz#52c249a3981b9ba187c7cacf5beb50bf1d91a6bc"
dependencies:
@ -2753,11 +2747,11 @@ extract-text-webpack-plugin@^3.0.2:
webpack-sources "^1.0.1"
extract-zip@^1.6.5:
version "1.6.5"
resolved "https://registry.yarnpkg.com/extract-zip/-/extract-zip-1.6.5.tgz#99a06735b6ea20ea9b705d779acffcc87cff0440"
version "1.6.6"
resolved "https://registry.yarnpkg.com/extract-zip/-/extract-zip-1.6.6.tgz#1290ede8d20d0872b429fd3f351ca128ec5ef85c"
dependencies:
concat-stream "1.6.0"
debug "2.2.0"
debug "2.6.9"
mkdirp "0.5.0"
yauzl "2.4.1"
@ -3093,8 +3087,8 @@ global-dirs@^0.1.0:
ini "^1.3.4"
globals@^10.0.0:
version "10.1.0"
resolved "https://registry.yarnpkg.com/globals/-/globals-10.1.0.tgz#4425a1881be0d336b4a823a82a7be725d5dd987c"
version "10.3.0"
resolved "https://registry.yarnpkg.com/globals/-/globals-10.3.0.tgz#716aba93657b56630b5a0e77de5ea8ac6215afaa"
globals@^9.17.0, globals@^9.18.0:
version "9.18.0"
@ -3401,10 +3395,6 @@ hullabaloo-config-manager@^1.1.0:
resolve-from "^3.0.0"
safe-buffer "^5.0.1"
iconv-lite@0.4.13:
version "0.4.13"
resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.13.tgz#1f88aba4ab0b1508e8312acc39345f36e992e2f2"
iconv-lite@0.4.19, iconv-lite@^0.4.17, iconv-lite@~0.4.13:
version "0.4.19"
resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.19.tgz#f7468f60135f5e5dad3399c0a81be9a1603a082b"
@ -3487,7 +3477,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:
@ -3505,6 +3495,25 @@ inquirer@3.0.6, inquirer@^3.0.6:
strip-ansi "^3.0.0"
through "^2.3.6"
inquirer@^3.0.6:
version "3.3.0"
resolved "https://registry.yarnpkg.com/inquirer/-/inquirer-3.3.0.tgz#9dd2f2ad765dcab1ff0443b491442a20ba227dc9"
dependencies:
ansi-escapes "^3.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.4"
resolved "https://registry.yarnpkg.com/interpret/-/interpret-1.0.4.tgz#820cdd588b868ffb191a809506d6c9c8f212b1b0"
@ -4276,7 +4285,7 @@ minimatch@^3.0.0, minimatch@^3.0.2, minimatch@^3.0.3, minimatch@^3.0.4:
dependencies:
brace-expansion "^1.1.7"
minimist@0.0.8, minimist@~0.0.1:
minimist@0.0.8:
version "0.0.8"
resolved "https://registry.yarnpkg.com/minimist/-/minimist-0.0.8.tgz#857fcabfc3397d2625b8228262e86aa7a011b05d"
@ -4284,6 +4293,10 @@ 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"
mississippi@^1.3.0:
version "1.3.0"
resolved "https://registry.yarnpkg.com/mississippi/-/mississippi-1.3.0.tgz#d201583eb12327e3c5c1642a404a9cacf94e34f5"
@ -4322,10 +4335,6 @@ move-concurrently@^1.0.1:
rimraf "^2.5.4"
run-queue "^1.0.3"
ms@0.7.1:
version "0.7.1"
resolved "https://registry.yarnpkg.com/ms/-/ms-0.7.1.tgz#9cd13c03adbff25b65effde7ce864ee952017098"
ms@2.0.0, ms@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/ms/-/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8"
@ -4413,9 +4422,10 @@ node-libs-browser@^2.0.0:
vm-browserify "0.0.4"
node-pre-gyp@^0.6.36:
version "0.6.38"
resolved "https://registry.yarnpkg.com/node-pre-gyp/-/node-pre-gyp-0.6.38.tgz#e92a20f83416415bb4086f6d1fb78b3da73d113d"
version "0.6.39"
resolved "https://registry.yarnpkg.com/node-pre-gyp/-/node-pre-gyp-0.6.39.tgz#c00e96860b23c0e1420ac7befc5044e1d78d8649"
dependencies:
detect-libc "^1.0.2"
hawk "3.1.3"
mkdirp "^0.5.1"
nopt "^4.0.1"
@ -4755,10 +4765,10 @@ parse-ms@^1.0.0:
resolved "https://registry.yarnpkg.com/parse-ms/-/parse-ms-1.0.1.tgz#56346d4749d78f23430ca0c713850aef91aa361d"
parse5@^3.0.2:
version "3.0.2"
resolved "https://registry.yarnpkg.com/parse5/-/parse5-3.0.2.tgz#05eff57f0ef4577fb144a79f8b9a967a6cc44510"
version "3.0.3"
resolved "https://registry.yarnpkg.com/parse5/-/parse5-3.0.3.tgz#042f792ffdd36851551cf4e9e066b3874ab45b5c"
dependencies:
"@types/node" "^6.0.46"
"@types/node" "*"
parseurl@~1.3.2:
version "1.3.2"
@ -4943,10 +4953,10 @@ postcss-calc@^6.0.0:
reduce-css-calc "^2.0.0"
postcss-color-function@^4.0.0:
version "4.0.0"
resolved "https://registry.yarnpkg.com/postcss-color-function/-/postcss-color-function-4.0.0.tgz#7e0106f4f6a1ecb1ad5b3a8553ace5e828aae187"
version "4.0.1"
resolved "https://registry.yarnpkg.com/postcss-color-function/-/postcss-color-function-4.0.1.tgz#402b3f2cebc3f6947e618fb6be3654fbecef6444"
dependencies:
css-color-function "^1.3.0"
css-color-function "~1.3.3"
postcss "^6.0.1"
postcss-message-helpers "^2.0.0"
postcss-value-parser "^3.3.0"
@ -5421,11 +5431,11 @@ postcss@^5.0.10, postcss@^5.0.11, postcss@^5.0.12, postcss@^5.0.13, postcss@^5.0
source-map "^0.5.6"
supports-color "^3.2.3"
postcss@^6.0.0, postcss@^6.0.1, postcss@^6.0.11, postcss@^6.0.13, postcss@^6.0.5, postcss@^6.0.6, postcss@^6.0.8:
version "6.0.13"
resolved "https://registry.yarnpkg.com/postcss/-/postcss-6.0.13.tgz#b9ecab4ee00c89db3ec931145bd9590bbf3f125f"
postcss@^6.0.0, postcss@^6.0.1, postcss@^6.0.11, postcss@^6.0.13, postcss@^6.0.14, postcss@^6.0.5, postcss@^6.0.6, postcss@^6.0.8:
version "6.0.14"
resolved "https://registry.yarnpkg.com/postcss/-/postcss-6.0.14.tgz#5534c72114739e75d0afcf017db853099f562885"
dependencies:
chalk "^2.1.0"
chalk "^2.3.0"
source-map "^0.6.1"
supports-color "^4.4.0"
@ -5442,8 +5452,8 @@ preserve@^0.2.0:
resolved "https://registry.yarnpkg.com/preserve/-/preserve-0.2.0.tgz#815ed1f6ebc65926f865b310c0713bcb3315ce4b"
prettier@^1.7.0:
version "1.7.4"
resolved "https://registry.yarnpkg.com/prettier/-/prettier-1.7.4.tgz#5e8624ae9363c80f95ec644584ecdf55d74f93fa"
version "1.8.0"
resolved "https://registry.yarnpkg.com/prettier/-/prettier-1.8.0.tgz#d9dc68277cf1ded816c8e8863ab47889c29ce9a6"
pretty-error@^2.0.2, pretty-error@^2.1.1:
version "2.1.1"
@ -5600,12 +5610,19 @@ randomatic@^1.1.3:
is-number "^3.0.0"
kind-of "^4.0.0"
randombytes@^2.0.0, randombytes@^2.0.1:
randombytes@^2.0.0, randombytes@^2.0.1, randombytes@^2.0.5:
version "2.0.5"
resolved "https://registry.yarnpkg.com/randombytes/-/randombytes-2.0.5.tgz#dc009a246b8d09a177b4b7a0ae77bc570f4b1b79"
dependencies:
safe-buffer "^5.1.0"
randomfill@^1.0.3:
version "1.0.3"
resolved "https://registry.yarnpkg.com/randomfill/-/randomfill-1.0.3.tgz#b96b7df587f01dd91726c418f30553b1418e3d62"
dependencies:
randombytes "^2.0.5"
safe-buffer "^5.1.0"
range-parser@^1.0.3, range-parser@~1.2.0:
version "1.2.0"
resolved "https://registry.yarnpkg.com/range-parser/-/range-parser-1.2.0.tgz#f49be6b487894ddc40dcc94a322f611092e00d5e"
@ -6059,6 +6076,16 @@ run-queue@^1.0.0, run-queue@^1.0.3:
dependencies:
aproba "^1.1.1"
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"
@ -6235,7 +6262,7 @@ source-map@0.5.6:
version "0.5.6"
resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.5.6.tgz#75ce38f52bf0733c5a7f0c118d81334a2bb5f412"
source-map@0.5.x, source-map@^0.5.0, source-map@^0.5.3, source-map@^0.5.6, source-map@~0.5.1, source-map@~0.5.3, source-map@~0.5.6:
source-map@0.5.x, source-map@^0.5.0, source-map@^0.5.3, source-map@^0.5.6, source-map@~0.5.1, source-map@~0.5.6:
version "0.5.7"
resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.5.7.tgz#8a039d2d1021d22d1ea14c80d8ea468ba2ef3fcc"
@ -6310,7 +6337,11 @@ stackframe@^1.0.3:
version "1.0.4"
resolved "https://registry.yarnpkg.com/stackframe/-/stackframe-1.0.4.tgz#357b24a992f9427cba6b545d96a14ed2cbca187b"
"statuses@>= 1.3.1 < 2", statuses@~1.3.1:
"statuses@>= 1.3.1 < 2":
version "1.4.0"
resolved "https://registry.yarnpkg.com/statuses/-/statuses-1.4.0.tgz#bb73d446da2796106efcc1b601a253d6c46bd087"
statuses@~1.3.1:
version "1.3.1"
resolved "https://registry.yarnpkg.com/statuses/-/statuses-1.3.1.tgz#faf51b9eb74aaef3b3acf4ad5f61abf24cb7b93e"
@ -6370,7 +6401,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.1:
string-width@^2.0.0, string-width@^2.1.0, string-width@^2.1.1:
version "2.1.1"
resolved "https://registry.yarnpkg.com/string-width/-/string-width-2.1.1.tgz#ab93f27a8dc13d28cac815c462143a6d9012ae9e"
dependencies:
@ -6657,15 +6688,15 @@ typedarray@^0.0.6:
resolved "https://registry.yarnpkg.com/typedarray/-/typedarray-0.0.6.tgz#867ac74e3864187b1d3d47d996a78ec5c8830777"
uglify-es@^3.1.3:
version "3.1.5"
resolved "https://registry.yarnpkg.com/uglify-es/-/uglify-es-3.1.5.tgz#63bae0fd4f9feeda417fee7c0ff685a673819683"
version "3.1.8"
resolved "https://registry.yarnpkg.com/uglify-es/-/uglify-es-3.1.8.tgz#2f21a56871d6354dcc21469cc034c3967f14c5b1"
dependencies:
commander "~2.11.0"
source-map "~0.6.1"
uglify-js@3.1.x:
version "3.1.5"
resolved "https://registry.yarnpkg.com/uglify-js/-/uglify-js-3.1.5.tgz#4c1a6d53b2fe77e4710dd94631853effd3ff5143"
uglify-js@3.1.x, uglify-js@^3.1.7:
version "3.1.8"
resolved "https://registry.yarnpkg.com/uglify-js/-/uglify-js-3.1.8.tgz#780d08b4f6782fe36ea5484d952362eddaf1d7b8"
dependencies:
commander "~2.11.0"
source-map "~0.6.1"
@ -6679,13 +6710,6 @@ uglify-js@^2.6, uglify-js@^2.8.29:
optionalDependencies:
uglify-to-browserify "~1.0.0"
uglify-js@^3.1.6:
version "3.1.6"
resolved "https://registry.yarnpkg.com/uglify-js/-/uglify-js-3.1.6.tgz#918832602036e95d2318e11f27ee8461a8592c5d"
dependencies:
commander "~2.11.0"
source-map "~0.6.1"
uglify-to-browserify@~1.0.0:
version "1.0.2"
resolved "https://registry.yarnpkg.com/uglify-to-browserify/-/uglify-to-browserify-1.0.2.tgz#6e0924d6bda6b5afe349e39a6d632850a0f882b7"
@ -6891,9 +6915,9 @@ vue-hot-reload-api@^2.2.0:
version "2.2.0"
resolved "https://registry.yarnpkg.com/vue-hot-reload-api/-/vue-hot-reload-api-2.2.0.tgz#9a21b35ced3634434a43ee80efb7350ea8fb206d"
vue-loader@^13.3.0:
version "13.3.0"
resolved "https://registry.yarnpkg.com/vue-loader/-/vue-loader-13.3.0.tgz#3bf837d490ba5dea6fc07e0835ffa6c688c8af33"
vue-loader@^13.4.0:
version "13.4.0"
resolved "https://registry.yarnpkg.com/vue-loader/-/vue-loader-13.4.0.tgz#44aa7eef4fb1be89fbc37193ad33b8253417c4b9"
dependencies:
consolidate "^0.14.0"
hash-sum "^1.0.2"
@ -6909,11 +6933,11 @@ vue-loader@^13.3.0:
vue-style-loader "^3.0.0"
vue-template-es2015-compiler "^1.6.0"
vue-meta@^1.2.0:
version "1.2.0"
resolved "https://registry.yarnpkg.com/vue-meta/-/vue-meta-1.2.0.tgz#f4cedccaae566ea0a27f052820dc076510d0080c"
vue-meta@^1.3.1:
version "1.3.1"
resolved "https://registry.yarnpkg.com/vue-meta/-/vue-meta-1.3.1.tgz#1c46c9af6119c61934a5b2783538b062c03be2c7"
dependencies:
deepmerge "^1.5.0"
deepmerge "^2.0.0"
lodash.isplainobject "^4.0.6"
object-assign "^4.1.1"
@ -6921,9 +6945,9 @@ vue-router@^3.0.1:
version "3.0.1"
resolved "https://registry.yarnpkg.com/vue-router/-/vue-router-3.0.1.tgz#d9b05ad9c7420ba0f626d6500d693e60092cc1e9"
vue-server-renderer@^2.5.2:
version "2.5.2"
resolved "https://registry.yarnpkg.com/vue-server-renderer/-/vue-server-renderer-2.5.2.tgz#c96a4368caa3fd298a528f1bf40632d8f696ff25"
vue-server-renderer@^2.5.3:
version "2.5.3"
resolved "https://registry.yarnpkg.com/vue-server-renderer/-/vue-server-renderer-2.5.3.tgz#cac10b4a9d147b04cf70cd8bc3ac95f5e630794b"
dependencies:
chalk "^1.1.3"
hash-sum "^1.0.2"
@ -6941,9 +6965,9 @@ vue-style-loader@^3.0.0:
hash-sum "^1.0.2"
loader-utils "^1.0.2"
vue-template-compiler@^2.5.2:
version "2.5.2"
resolved "https://registry.yarnpkg.com/vue-template-compiler/-/vue-template-compiler-2.5.2.tgz#6f198ebc677b8f804315cd33b91e849315ae7177"
vue-template-compiler@^2.5.3:
version "2.5.3"
resolved "https://registry.yarnpkg.com/vue-template-compiler/-/vue-template-compiler-2.5.3.tgz#ab631b0694e211a6aaf0d800102b37836aae36a4"
dependencies:
de-indent "^1.0.2"
he "^1.1.0"
@ -6952,9 +6976,9 @@ vue-template-es2015-compiler@^1.6.0:
version "1.6.0"
resolved "https://registry.yarnpkg.com/vue-template-es2015-compiler/-/vue-template-es2015-compiler-1.6.0.tgz#dc42697133302ce3017524356a6c61b7b69b4a18"
vue@^2.5.2:
version "2.5.2"
resolved "https://registry.yarnpkg.com/vue/-/vue-2.5.2.tgz#fd367a87bae7535e47f9dc5c9ec3b496e5feb5a4"
vue@^2.5.3:
version "2.5.3"
resolved "https://registry.yarnpkg.com/vue/-/vue-2.5.3.tgz#e1a3b1f49b6e93e574ce040b95cbc873912fecc1"
vuex@^3.0.1:
version "3.0.1"
@ -7012,11 +7036,11 @@ webpack-node-externals@^1.6.0:
resolved "https://registry.yarnpkg.com/webpack-node-externals/-/webpack-node-externals-1.6.0.tgz#232c62ec6092b100635a3d29d83c1747128df9bd"
webpack-sources@^1.0.1:
version "1.0.1"
resolved "https://registry.yarnpkg.com/webpack-sources/-/webpack-sources-1.0.1.tgz#c7356436a4d13123be2e2426a05d1dad9cbe65cf"
version "1.0.2"
resolved "https://registry.yarnpkg.com/webpack-sources/-/webpack-sources-1.0.2.tgz#d0148ec083b3b5ccef1035a6b3ec16442983b27a"
dependencies:
source-list-map "^2.0.0"
source-map "~0.5.3"
source-map "~0.6.1"
webpack@^3.8.1:
version "3.8.1"
@ -7050,10 +7074,10 @@ well-known-symbols@^1.0.0:
resolved "https://registry.yarnpkg.com/well-known-symbols/-/well-known-symbols-1.0.0.tgz#73c78ae81a7726a8fa598e2880801c8b16225518"
whatwg-encoding@^1.0.1:
version "1.0.2"
resolved "https://registry.yarnpkg.com/whatwg-encoding/-/whatwg-encoding-1.0.2.tgz#bd68ad169c3cf55080562257714bf012e668a165"
version "1.0.3"
resolved "https://registry.yarnpkg.com/whatwg-encoding/-/whatwg-encoding-1.0.3.tgz#57c235bc8657e914d24e1a397d3c82daee0a6ba3"
dependencies:
iconv-lite "0.4.13"
iconv-lite "0.4.19"
whatwg-url@^6.3.0:
version "6.3.0"
@ -7093,17 +7117,21 @@ 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"
worker-farm@^1.4.1:
version "1.5.0"
resolved "https://registry.yarnpkg.com/worker-farm/-/worker-farm-1.5.0.tgz#adfdf0cd40581465ed0a1f648f9735722afd5c8d"
version "1.5.1"
resolved "https://registry.yarnpkg.com/worker-farm/-/worker-farm-1.5.1.tgz#8e9f4a7da4f3c595aa600903051b969390423fa1"
dependencies:
errno "^0.1.4"
xtend "^4.0.1"
@ -7167,8 +7195,8 @@ ws@^2.3.1:
ultron "~1.1.0"
ws@^3.0.0:
version "3.2.0"
resolved "https://registry.yarnpkg.com/ws/-/ws-3.2.0.tgz#d5d3d6b11aff71e73f808f40cc69d52bb6d4a185"
version "3.3.0"
resolved "https://registry.yarnpkg.com/ws/-/ws-3.3.0.tgz#f8b948a1378af7efa702f5513da08dd516897c31"
dependencies:
async-limiter "~1.0.0"
safe-buffer "~5.1.0"