@nuxt/server
Advanced tools
Comparing version 2.3.4 to 2.4.0
@@ -6,2 +6,37 @@ # Change Log | ||
# [2.4.0](https://github.com/nuxt/nuxt.js/compare/v2.3.4...v2.4.0) (2019-01-28) | ||
### Bug Fixes | ||
* **deps:** update all non-major dependencies ([#4358](https://github.com/nuxt/nuxt.js/issues/4358)) ([45fdae0](https://github.com/nuxt/nuxt.js/commit/45fdae0)) | ||
* **server:** allow listening on number 0 port ([#4781](https://github.com/nuxt/nuxt.js/issues/4781)) ([602cf12](https://github.com/nuxt/nuxt.js/commit/602cf12)) | ||
* **server:** allow rendering urls with unicode characters ([#4512](https://github.com/nuxt/nuxt.js/issues/4512)) ([c3128ea](https://github.com/nuxt/nuxt.js/commit/c3128ea)) | ||
* **server:** Cannot read property client of null when webpackHMR & restarting Nuxt ([8a200f7](https://github.com/nuxt/nuxt.js/commit/8a200f7)) | ||
* **server:** process browser version with non semver versions ([#4673](https://github.com/nuxt/nuxt.js/issues/4673)) ([d3b9396](https://github.com/nuxt/nuxt.js/commit/d3b9396)) | ||
* **server, jsdom:** fix timeout error message ([#4412](https://github.com/nuxt/nuxt.js/issues/4412)) ([ab6367b](https://github.com/nuxt/nuxt.js/commit/ab6367b)) | ||
* **server, vue-app:** allow unicode page names ([#4402](https://github.com/nuxt/nuxt.js/issues/4402)) ([949785f](https://github.com/nuxt/nuxt.js/commit/949785f)) | ||
* add iron browser as modern ([#4775](https://github.com/nuxt/nuxt.js/issues/4775)) ([9eab558](https://github.com/nuxt/nuxt.js/commit/9eab558)) | ||
* csp SHA hashes accumulate when using custom script-src rules ([#4519](https://github.com/nuxt/nuxt.js/issues/4519)) ([683dbba](https://github.com/nuxt/nuxt.js/commit/683dbba)) | ||
* hmr in modern mode ([#4623](https://github.com/nuxt/nuxt.js/issues/4623)) ([df9b32a](https://github.com/nuxt/nuxt.js/commit/df9b32a)) | ||
* improvements for build and dev stability ([#4470](https://github.com/nuxt/nuxt.js/issues/4470)) ([fe05169](https://github.com/nuxt/nuxt.js/commit/fe05169)) | ||
* offer a new port and listen if already used, use consola on server error ([#4428](https://github.com/nuxt/nuxt.js/issues/4428)) ([1d78027](https://github.com/nuxt/nuxt.js/commit/1d78027)) | ||
* require serverMiddleware object with path and handler ([#4656](https://github.com/nuxt/nuxt.js/issues/4656)) ([8786ff7](https://github.com/nuxt/nuxt.js/commit/8786ff7)) | ||
* wrong devMiddleware in non-modern dev mode ([3515115](https://github.com/nuxt/nuxt.js/commit/3515115)) | ||
### Features | ||
* **modern:** auto detect modern mode ([#4422](https://github.com/nuxt/nuxt.js/issues/4422)) ([fe492d8](https://github.com/nuxt/nuxt.js/commit/fe492d8)) | ||
* **server:** export Listener ([#4577](https://github.com/nuxt/nuxt.js/issues/4577)) ([2f0ed85](https://github.com/nuxt/nuxt.js/commit/2f0ed85)) | ||
* better stack traces for SSR error, show error with correct URL and use eventsource-polyfill ([#4600](https://github.com/nuxt/nuxt.js/issues/4600)) ([498c4f1](https://github.com/nuxt/nuxt.js/commit/498c4f1)) | ||
* disable compressor if set to false/undefined ([#4381](https://github.com/nuxt/nuxt.js/issues/4381)) ([e4140ce](https://github.com/nuxt/nuxt.js/commit/e4140ce)) | ||
* improve SSR bundle ([#4439](https://github.com/nuxt/nuxt.js/issues/4439)) ([0f104aa](https://github.com/nuxt/nuxt.js/commit/0f104aa)), closes [#4225](https://github.com/nuxt/nuxt.js/issues/4225) [#3465](https://github.com/nuxt/nuxt.js/issues/3465) [#1728](https://github.com/nuxt/nuxt.js/issues/1728) [#1601](https://github.com/nuxt/nuxt.js/issues/1601) [#1481](https://github.com/nuxt/nuxt.js/issues/1481) | ||
* nuxt-ts ([#4658](https://github.com/nuxt/nuxt.js/issues/4658)) ([ee0096b](https://github.com/nuxt/nuxt.js/commit/ee0096b)) | ||
* **server:** timing option for `Server-Timing` header ([#4800](https://github.com/nuxt/nuxt.js/issues/4800)) ([b23f5c9](https://github.com/nuxt/nuxt.js/commit/b23f5c9)) | ||
## [2.3.4](https://github.com/nuxt/nuxt.js/compare/v2.3.2...v2.3.4) (2018-11-26) | ||
@@ -8,0 +43,0 @@ |
/*! | ||
* @nuxt/server v2.3.4 (c) 2016-2018 | ||
* @nuxt/server v2.4.0 (c) 2016-2019 | ||
@@ -14,2 +14,4 @@ * - All the amazing contributors | ||
const path = _interopDefault(require('path')); | ||
const consola = _interopDefault(require('consola')); | ||
const launchMiddleware = _interopDefault(require('launch-editor-middleware')); | ||
@@ -19,5 +21,5 @@ const serveStatic = _interopDefault(require('serve-static')); | ||
const connect = _interopDefault(require('connect')); | ||
const utils = require('@nuxt/utils'); | ||
const generateETag = _interopDefault(require('etag')); | ||
const fresh = _interopDefault(require('fresh')); | ||
const path = _interopDefault(require('path')); | ||
const fs = _interopDefault(require('fs-extra')); | ||
@@ -29,6 +31,7 @@ const Youch = _interopDefault(require('@nuxtjs/youch')); | ||
const ip = _interopDefault(require('ip')); | ||
const consola = _interopDefault(require('consola')); | ||
const pify = _interopDefault(require('pify')); | ||
const common = require('@nuxt/common'); | ||
const browserslistUseragent = require('browserslist-useragent'); | ||
const chalk = _interopDefault(require('chalk')); | ||
const UAParser = _interopDefault(require('ua-parser-js')); | ||
const semver = _interopDefault(require('semver')); | ||
const onHeaders = _interopDefault(require('on-headers')); | ||
@@ -104,3 +107,3 @@ class ServerContext { | ||
// Used by Nuxt.js to say when the components are loaded and the app ready | ||
await common.timeout(new Promise((resolve) => { | ||
await utils.timeout(new Promise((resolve) => { | ||
window[loadedCallback] = () => resolve(window); | ||
@@ -120,4 +123,4 @@ }), loadingTimeout, `Components loading in renderAndGetWindow was not completed in ${loadingTimeout / 1000}s`); | ||
// Get context | ||
const context = common.getContext(req, res); | ||
const url = req.url; | ||
const context = utils.getContext(req, res); | ||
const url = decodeURI(req.url); | ||
@@ -130,3 +133,3 @@ res.statusCode = 200; | ||
html, | ||
cspScriptSrcHashSet, | ||
cspScriptSrcHashes, | ||
error, | ||
@@ -168,3 +171,3 @@ redirected, | ||
? pushAssets(req, res, publicPath, preloadFiles) | ||
: defaultPushAssets(preloadFiles, shouldPush, publicPath, options.dev); | ||
: defaultPushAssets(preloadFiles, shouldPush, publicPath, options); | ||
@@ -183,3 +186,3 @@ // Pass with single Link header | ||
res.setHeader(cspHeader, getCspString({ cspScriptSrcHashSet, allowedSources, policies, isDev: options.dev })); | ||
res.setHeader(cspHeader, getCspString({ cspScriptSrcHashes, allowedSources, policies, isDev: options.dev })); | ||
} | ||
@@ -205,4 +208,4 @@ | ||
const defaultPushAssets = (preloadFiles, shouldPush, publicPath, isDev) => { | ||
if (shouldPush && isDev) { | ||
const defaultPushAssets = (preloadFiles, shouldPush, publicPath, options) => { | ||
if (shouldPush && options.dev) { | ||
consola.warn('http2.shouldPush is deprecated. Use http2.pushAssets function'); | ||
@@ -212,3 +215,3 @@ } | ||
const links = []; | ||
preloadFiles.forEach(({ file, asType, fileWithoutQuery }) => { | ||
preloadFiles.forEach(({ file, asType, fileWithoutQuery, modern }) => { | ||
// By default, we only preload scripts or css | ||
@@ -225,3 +228,7 @@ /* istanbul ignore if */ | ||
links.push(`<${publicPath}${file}>; rel=preload; as=${asType}`); | ||
const { crossorigin } = options.build; | ||
const cors = `${crossorigin ? ` crossorigin=${crossorigin};` : ''}`; | ||
const ref = modern ? 'modulepreload' : 'preload'; | ||
links.push(`<${publicPath}${file}>; rel=${ref};${cors} as=${asType}`); | ||
}); | ||
@@ -231,5 +238,5 @@ return links | ||
const getCspString = ({ cspScriptSrcHashSet, allowedSources, policies, isDev }) => { | ||
const joinedHashSet = Array.from(cspScriptSrcHashSet).join(' '); | ||
const baseCspStr = `script-src 'self'${isDev ? ` 'unsafe-eval'` : ''} ${joinedHashSet}`; | ||
const getCspString = ({ cspScriptSrcHashes, allowedSources, policies, isDev }) => { | ||
const joinedHashes = cspScriptSrcHashes.join(' '); | ||
const baseCspStr = `script-src 'self'${isDev ? ` 'unsafe-eval'` : ''} ${joinedHashes}`; | ||
@@ -243,3 +250,3 @@ if (Array.isArray(allowedSources)) { | ||
if (policyObjectAvailable) { | ||
const transformedPolicyObject = transformPolicyObject(policies, cspScriptSrcHashSet); | ||
const transformedPolicyObject = transformPolicyObject(policies, cspScriptSrcHashes); | ||
@@ -252,20 +259,11 @@ return Object.entries(transformedPolicyObject).map(([k, v]) => `${k} ${v.join(' ')}`).join('; ') | ||
const transformPolicyObject = (policies, cspScriptSrcHashSet) => { | ||
const transformPolicyObject = (policies, cspScriptSrcHashes) => { | ||
const userHasDefinedScriptSrc = policies['script-src'] && Array.isArray(policies['script-src']); | ||
const additionalPolicies = userHasDefinedScriptSrc ? policies['script-src'] : []; | ||
// Self is always needed for inline-scripts, so add it, no matter if the user specified script-src himself. | ||
const hashAndPolicyList = cspScriptSrcHashes.concat(`'self'`, additionalPolicies); | ||
const hashAndPolicySet = cspScriptSrcHashSet; | ||
hashAndPolicySet.add(`'self'`); | ||
if (!userHasDefinedScriptSrc) { | ||
policies['script-src'] = Array.from(hashAndPolicySet); | ||
return policies | ||
} | ||
new Set(policies['script-src']).forEach(src => hashAndPolicySet.add(src)); | ||
policies['script-src'] = Array.from(hashAndPolicySet); | ||
return policies | ||
return { ...policies, 'script-src': hashAndPolicyList } | ||
}; | ||
@@ -283,2 +281,3 @@ | ||
? new Error(err) : new Error(err.message || JSON.stringify(err)); | ||
if (err.stack) errorFull.stack = err.stack; | ||
errorFull.name = error.name; | ||
@@ -334,4 +333,3 @@ errorFull.statusCode = error.statusCode; | ||
rootDir: options.rootDir, | ||
buildDir: options.buildDir, | ||
resources | ||
buildDir: options.buildDir | ||
}), | ||
@@ -350,3 +348,3 @@ options.router.base, | ||
const readSourceFactory = ({ srcDir, rootDir, buildDir, resources }) => async function readSource(frame) { | ||
const readSourceFactory = ({ srcDir, rootDir, buildDir }) => async function readSource(frame) { | ||
// Remove webpack:/// & query string from the end | ||
@@ -385,13 +383,6 @@ const sanitizeName = name => | ||
} | ||
// Fallback: use server bundle | ||
// TODO: restore to if after https://github.com/istanbuljs/nyc/issues/595 fixed | ||
/* istanbul ignore next */ | ||
if (!frame.contents) { | ||
frame.contents = resources.serverBundle.files[frame.fileName]; | ||
} | ||
}; | ||
class Listener { | ||
constructor({ port, host, socket, https: https$$1, app }) { | ||
constructor({ port, host, socket, https: https$$1, app, dev }) { | ||
// Options | ||
@@ -403,2 +394,3 @@ this.port = port; | ||
this.app = app; | ||
this.dev = dev; | ||
@@ -415,6 +407,13 @@ // After listen | ||
// Destroy server by forcing every connection to be closed | ||
if (this.server.listening) { | ||
if (this.server && this.server.listening) { | ||
await this.server.destroy(); | ||
consola.debug('server closed'); | ||
} | ||
// Delete references | ||
this.listening = false; | ||
this._server = null; | ||
this.server = null; | ||
this.address = null; | ||
this.url = null; | ||
} | ||
@@ -429,2 +428,3 @@ | ||
} | ||
this.port = address.port; | ||
this.url = `http${this.https ? 's' : ''}://${this.host}:${this.port}`; | ||
@@ -444,5 +444,6 @@ return | ||
const protocol = this.https ? https : http; | ||
const protocolOpts = typeof this.https === 'object' ? [ this.https ] : []; | ||
const protocolOpts = typeof this.https === 'object' ? [this.https] : []; | ||
this._server = protocol.createServer.apply(protocol, protocolOpts.concat(this.app)); | ||
// Call server.listen | ||
// Prepare listenArgs | ||
@@ -453,5 +454,10 @@ const listenArgs = this.socket ? { path: this.socket } : { host: this.host, port: this.port }; | ||
// Call server.listen | ||
this.server = await new Promise((resolve, reject) => { | ||
const s = this._server.listen(listenArgs, error => error ? reject(error) : resolve(s)); | ||
}); | ||
try { | ||
this.server = await new Promise((resolve, reject) => { | ||
this._server.on('error', error => reject(error)); | ||
const s = this._server.listen(listenArgs, error => error ? reject(error) : resolve(s)); | ||
}); | ||
} catch (error) { | ||
return this.serverErrorHandler(error) | ||
} | ||
@@ -462,2 +468,3 @@ // Enable destroy support | ||
// Compute listen URL | ||
this.computeURL(); | ||
@@ -468,22 +475,142 @@ | ||
} | ||
serverErrorHandler(error) { | ||
// Detect if port is not available | ||
const addressInUse = error.code === 'EADDRINUSE'; | ||
// Use better error message | ||
if (addressInUse) { | ||
error.message = `Address \`${this.host}:${this.port}\` is already in use.`; | ||
} | ||
// Listen to a random port on dev as a fallback | ||
if (addressInUse && this.dev && this.port !== '0') { | ||
consola.warn(error.message); | ||
consola.info('Trying a random port...'); | ||
this.port = '0'; | ||
return this.close().then(() => this.listen()) | ||
} | ||
// Throw error | ||
throw error | ||
} | ||
} | ||
const modernBrowsers = Object.keys(common.ModernBrowsers) | ||
.map(browser => `${browser} >= ${common.ModernBrowsers[browser]}`); | ||
const ModernBrowsers = { | ||
Edge: '16', | ||
Firefox: '60', | ||
Chrome: '61', | ||
'Chrome Headless': '61', | ||
Chromium: '61', | ||
Iron: '61', | ||
Safari: '10.1', | ||
Opera: '48', | ||
Yandex: '18', | ||
Vivaldi: '1.14', | ||
'Mobile Safari': '10.3' | ||
}; | ||
const modernBrowsers = Object.keys(ModernBrowsers) | ||
.reduce((allBrowsers, browser) => { | ||
allBrowsers[browser] = semver.coerce(ModernBrowsers[browser]); | ||
return allBrowsers | ||
}, {}); | ||
const isModernBrowser = (ua) => { | ||
return Boolean(ua) && browserslistUseragent.matchesUA(ua, { | ||
allowHigherVersions: true, | ||
browsers: modernBrowsers | ||
}) | ||
if (!ua) { | ||
return false | ||
} | ||
const { browser } = UAParser(ua); | ||
const browserVersion = semver.coerce(browser.version); | ||
if (!browserVersion) { | ||
return false | ||
} | ||
return modernBrowsers[browser.name] && semver.gte(browserVersion, modernBrowsers[browser.name]) | ||
}; | ||
function modernMiddleware (req, res, next) { | ||
const { socket = {}, headers } = req; | ||
if (socket.modernMode === undefined) { | ||
let detected = false; | ||
const detectModernBuild = ({ options, resources }) => { | ||
if (detected === false && ![false, 'client', 'server'].includes(options.modern)) { | ||
detected = true; | ||
if (resources.modernManifest) { | ||
options.modern = options.render.ssr ? 'server' : 'client'; | ||
consola.info(`Modern bundles are detected. Modern mode (${chalk.green.bold(options.modern)}) is enabled now.`); | ||
} else { | ||
options.modern = false; | ||
} | ||
} | ||
}; | ||
const detectModernBrowser = ({ socket = {}, headers }) => { | ||
if (socket.isModernBrowser === undefined) { | ||
const ua = headers && headers['user-agent']; | ||
socket.modernMode = isModernBrowser(ua); | ||
socket.isModernBrowser = isModernBrowser(ua); | ||
} | ||
req.modernMode = socket.modernMode; | ||
}; | ||
const setModernMode = (req, options) => { | ||
const { socket = {} } = req; | ||
const { isModernBrowser } = socket; | ||
if (options.modern === 'server') { | ||
req.modernMode = isModernBrowser; | ||
} | ||
if (options.dev && !!options.modern) { | ||
req.devModernMode = isModernBrowser; | ||
} | ||
}; | ||
const createModernMiddleware = ({ context }) => (req, res, next) => { | ||
detectModernBuild(context); | ||
detectModernBrowser(req); | ||
setModernMode(req, context.options); | ||
next(); | ||
}; | ||
const createTimingMiddleware = options => (req, res, next) => { | ||
if (res.timing) { | ||
consola.warn('server-timing is already registered.'); | ||
} | ||
res.timing = new ServerTiming(); | ||
if (options && options.total) { | ||
res.timing.start('total', 'Nuxt Server Time'); | ||
} | ||
onHeaders(res, () => { | ||
res.timing.end('total'); | ||
res.setHeader( | ||
'Server-Timing', | ||
[] | ||
.concat(res.getHeader('Server-Timing') || []) | ||
.concat(res.timing.headers) | ||
.join(', ') | ||
); | ||
}); | ||
next(); | ||
}; | ||
class ServerTiming extends utils.Timer { | ||
constructor(...args) { | ||
super(...args); | ||
this.headers = []; | ||
} | ||
end(...args) { | ||
const time = super.end(...args); | ||
this.headers.push(this.formatHeader(time)); | ||
return time | ||
} | ||
clear() { | ||
super.clear(); | ||
this.headers.length = 0; | ||
} | ||
formatHeader(time) { | ||
const desc = time.description ? `;desc="${time.description}"` : ''; | ||
return `${time.name};dur=${time.duration}${desc}` | ||
} | ||
} | ||
@@ -496,5 +623,5 @@ | ||
this.globals = common.determineGlobals(nuxt.options.globalName, nuxt.options.globals); | ||
this.globals = utils.determineGlobals(nuxt.options.globalName, nuxt.options.globals); | ||
this.publicPath = common.isUrl(this.options.build.publicPath) | ||
this.publicPath = utils.isUrl(this.options.build.publicPath) | ||
? this.options.build._publicPath | ||
@@ -515,2 +642,5 @@ : this.options.build.publicPath; | ||
this.app = connect(); | ||
// Close hook | ||
this.nuxt.hook('close', () => this.close()); | ||
} | ||
@@ -533,10 +663,2 @@ | ||
await this.nuxt.callHook('render:done', this); | ||
// Close all listeners after nuxt close | ||
this.nuxt.hook('close', async () => { | ||
for (const listener of this.listeners) { | ||
await listener.close(); | ||
} | ||
this.listeners = []; | ||
}); | ||
} | ||
@@ -550,3 +672,3 @@ | ||
if (!this.options.dev) { | ||
const compressor = this.options.render.compressor; | ||
const { compressor } = this.options.render; | ||
if (typeof compressor === 'object') { | ||
@@ -556,4 +678,4 @@ // If only setting for `compression` are provided, require the module and insert | ||
this.useMiddleware(compression(compressor)); | ||
} else { | ||
// Else, require own compression middleware | ||
} else if (compressor) { | ||
// Else, require own compression middleware if compressor is actually truthy | ||
this.useMiddleware(compressor); | ||
@@ -563,14 +685,19 @@ } | ||
if (this.options.modern === 'server') { | ||
this.useMiddleware(modernMiddleware); | ||
if (this.options.server.timing) { | ||
this.useMiddleware(createTimingMiddleware(this.options.server.timing)); | ||
} | ||
const modernMiddleware = createModernMiddleware({ | ||
context: this.renderer.context | ||
}); | ||
// Add webpack middleware support only for development | ||
if (this.options.dev) { | ||
this.useMiddleware(modernMiddleware); | ||
this.useMiddleware(async (req, res, next) => { | ||
const name = req.modernMode ? 'modern' : 'client'; | ||
if (this.devMiddleware[name]) { | ||
const name = req.devModernMode ? 'modern' : 'client'; | ||
if (this.devMiddleware && this.devMiddleware[name]) { | ||
await this.devMiddleware[name](req, res); | ||
} | ||
if (this.hotMiddleware[name]) { | ||
if (this.hotMiddleware && this.hotMiddleware[name]) { | ||
await this.hotMiddleware[name](req, res); | ||
@@ -609,8 +736,9 @@ } | ||
}); | ||
this.useMiddleware(modernMiddleware); | ||
} | ||
// Add user provided middleware | ||
this.options.serverMiddleware.forEach((m) => { | ||
for (const m of this.options.serverMiddleware) { | ||
this.useMiddleware(m); | ||
}); | ||
} | ||
@@ -659,12 +787,26 @@ const { fallback } = this.options.render; | ||
useMiddleware(middleware) { | ||
// Resolve middleware | ||
if (typeof middleware === 'string') { | ||
middleware = this.nuxt.resolver.requireModule(middleware); | ||
} | ||
let handler = middleware.handler || middleware; | ||
// Resolve handler | ||
if (typeof middleware.handler === 'string') { | ||
middleware.handler = this.nuxt.resolver.requireModule(middleware.handler); | ||
// Resolve handler setup as string (path) | ||
if (typeof handler === 'string') { | ||
try { | ||
const requiredModuleFromHandlerPath = this.nuxt.resolver.requireModule(handler); | ||
// In case the "handler" is not derived from an object but is a normal string, another object with | ||
// path and handler could be the result | ||
// If the required module has handler, treat the module as new "middleware" object | ||
if (requiredModuleFromHandlerPath.handler) { | ||
middleware = requiredModuleFromHandlerPath; | ||
} | ||
handler = requiredModuleFromHandlerPath.handler || requiredModuleFromHandlerPath; | ||
} catch (err) { | ||
consola.error(err); | ||
// Throw error in production mode | ||
if (!this.options.dev) { | ||
throw err | ||
} | ||
} | ||
} | ||
const handler = middleware.handler || middleware; | ||
@@ -700,7 +842,8 @@ // Resolve path | ||
const listener = new Listener({ | ||
port: port || this.options.server.port, | ||
port: isNaN(parseInt(port)) ? this.options.server.port : port, | ||
host: host || this.options.server.host, | ||
socket: socket || this.options.server.socket, | ||
https: this.options.server.https, | ||
app: this.app | ||
app: this.app, | ||
dev: this.options.dev | ||
}); | ||
@@ -716,4 +859,28 @@ | ||
} | ||
async close() { | ||
if (this.__closed) { | ||
return | ||
} | ||
this.__closed = true; | ||
for (const listener of this.listeners) { | ||
await listener.close(); | ||
} | ||
this.listeners = []; | ||
if (typeof this.renderer.close === 'function') { | ||
await this.renderer.close(); | ||
} | ||
this.app.removeAllListeners(); | ||
this.app = null; | ||
for (const key in this.resources) { | ||
delete this.resources[key]; | ||
} | ||
} | ||
} | ||
exports.Server = Server; | ||
exports.Listener = Listener; |
{ | ||
"name": "@nuxt/server", | ||
"version": "2.3.4", | ||
"version": "2.4.0", | ||
"repository": "nuxt/nuxt.js", | ||
@@ -11,10 +11,9 @@ "license": "MIT", | ||
"dependencies": { | ||
"@nuxt/common": "2.3.4", | ||
"@nuxt/config": "2.3.4", | ||
"@nuxt/config": "2.4.0", | ||
"@nuxt/utils": "2.4.0", | ||
"@nuxtjs/youch": "^4.2.3", | ||
"browserslist-useragent": "^2.0.1", | ||
"chalk": "^2.4.1", | ||
"chalk": "^2.4.2", | ||
"compression": "^1.7.3", | ||
"connect": "^3.6.6", | ||
"consola": "^2.3.0", | ||
"consola": "^2.3.2", | ||
"etag": "^1.8.1", | ||
@@ -25,6 +24,9 @@ "fresh": "^0.5.2", | ||
"launch-editor-middleware": "^2.2.1", | ||
"on-headers": "^1.0.1", | ||
"pify": "^4.0.1", | ||
"semver": "^5.6.0", | ||
"serve-placeholder": "^1.1.0", | ||
"serve-static": "^1.13.2", | ||
"server-destroy": "^1.0.1" | ||
"server-destroy": "^1.0.1", | ||
"ua-parser-js": "^0.7.19" | ||
}, | ||
@@ -31,0 +33,0 @@ "publishConfig": { |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
New author
Supply chain riskA new npm collaborator published a version of the package for the first time. New collaborators are usually benign additions to a project, but do indicate a change to the security surface area of a package.
Found 1 instance in 1 package
29859
717
2
19
+ Added@nuxt/utils@2.4.0
+ Addedon-headers@^1.0.1
+ Addedsemver@^5.6.0
+ Addedua-parser-js@^0.7.19
+ Added@nuxt/config@2.4.0(transitive)
+ Added@nuxt/utils@2.4.0(transitive)
+ Addedserialize-javascript@1.9.1(transitive)
+ Addedua-parser-js@0.7.39(transitive)
- Removed@nuxt/common@2.3.4
- Removedbrowserslist-useragent@^2.0.1
- Removed@nuxt/common@2.3.4(transitive)
- Removed@nuxt/config@2.3.4(transitive)
- Removedbrowserslist@4.24.2(transitive)
- Removedbrowserslist-useragent@2.0.1(transitive)
- Removedcaniuse-lite@1.0.30001679(transitive)
- Removedelectron-to-chromium@1.5.55(transitive)
- Removedescalade@3.2.0(transitive)
- Removedlru-cache@4.1.5(transitive)
- Removednode-releases@2.0.18(transitive)
- Removedos-tmpdir@1.0.2(transitive)
- Removedpseudomap@1.0.2(transitive)
- Removedtmp@0.0.33(transitive)
- Removedupdate-browserslist-db@1.1.1(transitive)
- Removeduseragent@2.3.0(transitive)
- Removedyallist@2.1.2(transitive)
Updated@nuxt/config@2.4.0
Updatedchalk@^2.4.2
Updatedconsola@^2.3.2