feat: support plug-and-play, typescript runtime and native modules (#8389)

Co-authored-by: Clark Du <clark.duxin@gmail.com>
This commit is contained in:
pooya parsa 2020-12-22 18:07:50 +01:00 committed by GitHub
parent 03384d3fbc
commit dec8f99fc3
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
77 changed files with 523 additions and 470 deletions

View File

@ -3,8 +3,8 @@
"scripts": {
"build": "npm run nuxt -- build",
"start": "npm run build && npm run nuxt -- start",
"nuxt": "node -r esm ../packages/cli/bin/nuxt-cli.js",
"nuxt": "jiti ../packages/cli/bin/nuxt-cli.js",
"bench:stateless": "ab -c1 -n3000 http://127.0.0.1:3000/stateless",
"bench:stateless-big": "ab -c1 -n500 http://127.0.0.1:3000/stateless-big"
}
}
}

View File

@ -4,6 +4,8 @@ if (process.argv[2] !== 'start') {
process.argv.splice(2, 0, 'start')
}
global.__NUXT_PATHS__ = (global.__NUXT_PATHS__ || []).concat(__dirname)
const suffix = require('../package.json').name.includes('-edge') ? '-edge' : ''
require('@nuxt/cli' + suffix).run()
.catch((error) => {

View File

@ -19,5 +19,19 @@ export default {
await pkg.writePackage()
}
}
},
ignoreUnused: [
// directly used by bin
'@nuxt/cli',
// discovered by config
'@nuxt/telemetry',
// vue-app externals for ssr
'node-fetch',
'vue',
'vue-client-only',
'vue-meta',
'vue-no-ssr',
'vue-router',
'vuex'
]
}

View File

@ -1,5 +1,7 @@
#!/usr/bin/env node
global.__NUXT_PATHS__ = (global.__NUXT_PATHS__ || []).concat(__dirname)
const suffix = require('../package.json').name.includes('-edge') ? '-edge' : ''
require('@nuxt/cli' + suffix).run()
.catch((error) => {

View File

@ -9,5 +9,13 @@ export default {
'README.md'
])
}
}
},
ignoreUnused: [
// used by postinstall
'@nuxt/opencollective',
// discovered by config
'@nuxt/components',
'@nuxt/loading-screen',
'@nuxt/telemetry'
]
}

View File

@ -48,7 +48,9 @@
}
],
"main": "dist/nuxt.js",
"bin": "bin/nuxt.js",
"bin": {
"nuxt": "./bin/nuxt.js"
},
"files": [
"bin",
"dist",
@ -65,8 +67,7 @@
"@nuxt/generator": "2.14.12",
"@nuxt/loading-screen": "^2.0.3",
"@nuxt/opencollective": "^0.3.2",
"@nuxt/telemetry": "^1.3.0",
"@nuxt/webpack": "2.14.12"
"@nuxt/telemetry": "^1.3.0"
},
"engines": {
"node": ">=10.13.0",

View File

@ -1,4 +1,5 @@
export * from '@nuxt/core'
export * from '@nuxt/builder'
export * from '@nuxt/generator'
export { getWebpackConfig } from '@nuxt/cli'

View File

@ -12,18 +12,18 @@
"scripts": {
"audit": "improved-yarn-audit --ignore-dev-deps --min-severity moderate -e 1548",
"build": "yarn clean && yarn pkg",
"changelog": "node -r esm scripts/changelog.js",
"changelog": "jiti scripts/changelog.js",
"clean": "yarn clean:build && yarn clean:examples && yarn clean:test",
"clean:build": "rimraf distributions/*/dist packages/*/dist",
"clean:examples": "rimraf examples/*/dist examples/*/.nuxt",
"clean:test": "rimraf test/fixtures/*/dist test/fixtures/*/.nuxt*/",
"dev": "node -r esm ./scripts/dev.js",
"dev": "jiti ./scripts/dev.js",
"postinstall": "lerna link && yarn dev",
"lint": "eslint --ext .js,.mjs,.vue .",
"lint:app": "eslint-multiplexer eslint --ignore-path packages/vue-app/template/.eslintignore 'test/fixtures/!(missing-plugin)/.nuxt!(-dev)/**' | eslint-multiplexer -b",
"ls-lint": "npx @ls-lint/ls-lint",
"nuxt": "node -r esm ./packages/cli/bin/nuxt-cli.js",
"pkg": "node -r esm ./scripts/package",
"nuxt": "jiti ./packages/cli/bin/nuxt-cli.js",
"pkg": "jiti ./scripts/package",
"test": "yarn test:fixtures && yarn test:dev && yarn test:unit && test:types",
"test:dev": "jest test/dev --forceExit",
"test:e2e": "jest -i test/e2e --forceExit",
@ -51,7 +51,6 @@
"cross-spawn": "^7.0.3",
"eslint": "^7.16.0",
"eslint-multiplexer": "^2.0.0",
"esm": "^3.2.25",
"execa": "^5.0.0",
"express": "^4.17.1",
"finalhandler": "^1.1.2",

View File

@ -4,14 +4,14 @@ const coreJsMeta = {
es6: 'es6',
es7: 'es7'
},
builtIns: '@babel/compat-data/corejs2-built-ins'
builtIns: require.resolve('@babel/compat-data/corejs2-built-ins')
},
3: {
prefixes: {
es6: 'es',
es7: 'es'
},
builtIns: 'core-js-compat/data'
builtIns: require.resolve('core-js-compat/data')
}
}

View File

@ -1,3 +1,7 @@
export default {
build: true
build: true,
ignoreUnused: [
// used for legacy _ in template context
'lodash'
]
}

View File

@ -23,8 +23,7 @@
"pify": "^5.0.0",
"semver": "^7.3.4",
"serialize-javascript": "^5.0.1",
"upath": "^2.0.1",
"url-polyfill": "^1.1.12"
"upath": "^2.0.1"
},
"publishConfig": {
"access": "public"

View File

@ -8,13 +8,7 @@ import hash from 'hash-sum'
import pify from 'pify'
import upath from 'upath'
import semver from 'semver'
import debounce from 'lodash/debounce'
import omit from 'lodash/omit'
import template from 'lodash/template'
import uniq from 'lodash/uniq'
import uniqBy from 'lodash/uniqBy'
import { debounce, omit, template, uniq, uniqBy } from 'lodash'
import {
r,
createRoutes,
@ -27,6 +21,9 @@ import {
TARGETS
} from '@nuxt/utils'
import { template as VueAppTemplate } from '@nuxt/vue-app'
import { BundleBuilder as WebpackBuilder } from '@nuxt/webpack'
import Ignore from './ignore'
import BuildContext from './context/build'
import TemplateContext from './context/template'
@ -74,7 +71,7 @@ export default class Builder {
}
// Resolve template
this.template = this.options.build.template || '@nuxt/vue-app'
this.template = this.options.build.template || VueAppTemplate
if (typeof this.template === 'string') {
this.template = this.nuxt.resolver.requireModule(this.template).template
}
@ -96,7 +93,7 @@ export default class Builder {
const context = new BuildContext(this)
if (typeof BundleBuilder !== 'function') {
({ BundleBuilder } = require('@nuxt/webpack'))
BundleBuilder = WebpackBuilder
}
return new BundleBuilder(context)

View File

@ -1,10 +1,10 @@
import hash from 'hash-sum'
import consola from 'consola'
import uniqBy from 'lodash/uniqBy'
import { uniqBy } from 'lodash'
import serialize from 'serialize-javascript'
import devalue from '@nuxt/devalue'
import { r, wp, wChunk, serializeFunction, isFullStatic } from '@nuxt/utils'
import { r, wp, wChunk, serializeFunction, isFullStatic, requireModule } from '@nuxt/utils'
export default class TemplateContext {
constructor (builder, options) {
@ -70,7 +70,7 @@ export default class TemplateContext {
get (target, prop) {
if (!lodash) {
consola.warn('Avoid using _ inside templates')
lodash = require('lodash')
lodash = requireModule('lodash')
}
return lodash[prop]
}

View File

@ -17,7 +17,7 @@ export const createNuxt = () => ({
hook: jest.fn(),
callHook: jest.fn(),
resolver: {
requireModule: jest.fn(() => ({ template: 'builder-template' })),
requireModule: jest.fn(),
resolveAlias: jest.fn(src => `resolveAlias(${src})`),
resolvePath: jest.fn(src => `resolvePath(${src})`)
}

View File

@ -1,9 +1,11 @@
import consola from 'consola'
import { template as VueAppTemplate } from '@nuxt/vue-app'
import { relativeTo, determineGlobals } from '@nuxt/utils'
import Builder from '../src/builder'
import { createNuxt } from './__utils__'
jest.mock('@nuxt/vue-app')
jest.mock('@nuxt/utils')
jest.mock('../src/ignore')
@ -37,9 +39,7 @@ describe('builder: builder constructor', () => {
expect(builder._buildStatus).toEqual(1)
expect(nuxt.resolver.requireModule).toBeCalledTimes(1)
expect(nuxt.resolver.requireModule).toBeCalledWith('@nuxt/vue-app')
expect(builder.template).toEqual('builder-template')
expect(builder.template).toBe(VueAppTemplate)
expect(builder.bundleBuilder).toBe(bundleBuilder)
})
@ -112,6 +112,5 @@ describe('builder: builder constructor', () => {
const builder = new Builder(nuxt, bundleBuilder)
expect(builder.template).toBe(nuxt.options.build.template)
expect(nuxt.resolver.requireModule).not.toBeCalled()
})
})

View File

@ -1,8 +1,8 @@
import path from 'path'
import lodash from 'lodash'
import Glob from 'glob'
import fs from 'fs-extra'
import consola from 'consola'
import template from 'lodash/template'
import { r, createRoutes, stripWhitespace } from '@nuxt/utils'
import { BundleBuilder } from '@nuxt/webpack'
import Builder from '../src/builder'
@ -10,9 +10,12 @@ import TemplateContext from '../src/context/template'
import { createNuxt } from './__utils__'
jest.mock('glob')
jest.mock('lodash', () => ({
...jest.requireActual('lodash'),
template: jest.fn()
}))
jest.mock('pify', () => fn => fn)
jest.mock('fs-extra')
jest.mock('lodash/template')
jest.mock('@nuxt/utils')
jest.mock('../src/context/template', () => jest.fn())
jest.mock('../src/ignore', () => function () {
@ -373,7 +376,7 @@ describe('builder: builder generate', () => {
const builder = new Builder(nuxt, BundleBuilder)
builder.relativeToBuild = jest.fn()
const templateFn = jest.fn(() => 'compiled content')
template.mockImplementation(() => templateFn)
lodash.template.mockImplementation(() => templateFn)
stripWhitespace.mockImplementation(content => `trim(${content})`)
const templateContext = {
@ -403,10 +406,10 @@ describe('builder: builder generate', () => {
expect(fs.readFile).nthCalledWith(1, '/var/nuxt/src/foo.js', 'utf8')
expect(fs.readFile).nthCalledWith(2, '/var/nuxt/src/bar.js', 'utf8')
expect(fs.readFile).nthCalledWith(3, '/var/nuxt/src/baz.js', 'utf8')
expect(template).toBeCalledTimes(3)
expect(template).nthCalledWith(1, 'readFile(/var/nuxt/src/foo.js, utf8)', templateContext.templateOptions)
expect(template).nthCalledWith(2, 'readFile(/var/nuxt/src/bar.js, utf8)', templateContext.templateOptions)
expect(template).nthCalledWith(3, 'readFile(/var/nuxt/src/baz.js, utf8)', templateContext.templateOptions)
expect(lodash.template).toBeCalledTimes(3)
expect(lodash.template).nthCalledWith(1, 'readFile(/var/nuxt/src/foo.js, utf8)', templateContext.templateOptions)
expect(lodash.template).nthCalledWith(2, 'readFile(/var/nuxt/src/bar.js, utf8)', templateContext.templateOptions)
expect(lodash.template).nthCalledWith(3, 'readFile(/var/nuxt/src/baz.js, utf8)', templateContext.templateOptions)
expect(templateFn).toBeCalledTimes(3)
expect(templateFn).nthCalledWith(1, {
...templateContext.templateVars,
@ -442,7 +445,7 @@ describe('builder: builder generate', () => {
const nuxt = createNuxt()
const builder = new Builder(nuxt, BundleBuilder)
builder.relativeToBuild = jest.fn()
template.mockImplementation(() => {
lodash.template.mockImplementation(() => {
throw new Error('compile failed')
})

View File

@ -1,24 +1,25 @@
import path from 'path'
import chokidar from 'chokidar'
import upath from 'upath'
import debounce from 'lodash/debounce'
import { debounce } from 'lodash'
import { r, isString, isPureObject } from '@nuxt/utils'
import { BundleBuilder } from '@nuxt/webpack'
import Builder from '../src/builder'
import { createNuxt } from './__utils__'
jest.mock('@nuxt/webpack')
jest.mock('lodash', () => ({
...jest.requireActual('lodash'),
debounce: jest.fn(fn => fn)
}))
jest.mock('chokidar', () => ({
watch: jest.fn().mockReturnThis(),
on: jest.fn().mockReturnThis(),
close: jest.fn().mockReturnThis()
}))
jest.mock('upath', () => ({ normalizeSafe: jest.fn(src => src) }))
jest.mock('lodash/debounce', () => jest.fn(fn => fn))
jest.mock('@nuxt/utils')
jest.mock('../src/ignore')
jest.mock('@nuxt/webpack')
jest.mock('../src/ignore')
describe('builder: builder watch', () => {
beforeEach(() => {

View File

@ -6,7 +6,11 @@ import devalue from '@nuxt/devalue'
import { r, wp, wChunk, serializeFunction } from '@nuxt/utils'
import TemplateContext from '../../src/context/template'
jest.mock('lodash', () => ({ test: 'test lodash', warn: 'only once' }))
jest.mock('lodash', () => ({
...jest.requireActual('lodash'),
test: 'test lodash',
warn: 'only once'
}))
describe('builder: buildContext', () => {
const builder = {

View File

@ -1,3 +1,5 @@
export default {
build: true
build: true,
ignoreUnused: ['crc'],
externals: ['crc/lib/crc32']
}

View File

@ -20,13 +20,14 @@
"connect": "^3.7.0",
"consola": "^2.15.0",
"crc": "^3.8.0",
"defu": "^3.2.2",
"destr": "^1.0.1",
"esm": "^3.2.25",
"execa": "^5.0.0",
"exit": "^0.1.2",
"fs-extra": "^9.0.1",
"globby": "^11.0.1",
"hable": "^3.0.0",
"lodash": "^4.4.2",
"minimist": "^1.2.5",
"opener": "1.5.2",
"pretty-bytes": "^5.4.1",

View File

@ -1,6 +1,6 @@
import util from 'util'
import consola from 'consola'
import get from 'lodash/get'
import { get } from 'lodash'
import { common } from '../options'
export default {

View File

@ -1,31 +1,18 @@
import path from 'path'
import { requireModule } from '@nuxt/utils'
const localNodeModules = path.resolve(process.cwd(), 'node_modules')
// Prefer importing modules from local node_modules (for NPX and global bin)
async function _import (modulePath) {
for (const mp of [
path.resolve(localNodeModules, modulePath),
modulePath
]) {
try {
return await import(mp)
} catch (e) {
if (e.code !== 'MODULE_NOT_FOUND') {
throw e
}
export const importModule = (id) => {
try {
return Promise.resolve(requireModule(id))
} catch (err) {
if (err.code === 'MODULE_NOT_FOUND') {
err.message = `Cannot import module '${id}'`
}
return Promise.reject(err)
}
const error = new Error(`Cannot import module '${modulePath}'`)
error.code = 'MODULE_NOT_FOUND'
throw error
}
export const builder = () => _import('@nuxt/builder')
export const webpack = () => _import('@nuxt/webpack')
export const generator = () => _import('@nuxt/generator')
export const core = () => _import('@nuxt/core')
export const server = () => _import('@nuxt/server')
export const importModule = _import
export const builder = () => importModule('@nuxt/builder')
export const webpack = () => importModule('@nuxt/webpack')
export const generator = () => importModule('@nuxt/generator')
export const core = () => importModule('@nuxt/core')
export const server = () => importModule('@nuxt/server')

View File

@ -2,6 +2,7 @@ import { existsSync } from 'fs'
import { resolve } from 'path'
import execa from 'execa'
import consola from 'consola'
import { requireModule } from '@nuxt/utils'
import { name as pkgName } from '../package.json'
import NuxtCommand from './command'
import setup from './setup'
@ -12,7 +13,7 @@ export default async function run (_argv, hooks = {}) {
// Check for not installing both nuxt and nuxt-edge
const dupPkg = pkgName === '@nuxt/cli-edge' ? 'cli' : 'cli-edge'
const dupPkgJSON = resolve(__dirname, '../..' /* dist/../.. */, dupPkg, 'package.json')
if (existsSync(dupPkgJSON) && require(dupPkgJSON).name !== '@nuxt/' + dupPkg) {
if (existsSync(dupPkgJSON) && requireModule(dupPkgJSON).name !== '@nuxt/' + dupPkg) {
consola.warn('Both `nuxt` and `nuxt-edge` dependencies are installed! Please choose one and remove the other one from dependencies.')
}

View File

@ -1,5 +1,5 @@
import path from 'path'
import defaultsDeep from 'lodash/defaultsDeep'
import defu from 'defu'
import { loadNuxtConfig as _loadNuxtConfig, getDefaultNuxtConfig } from '@nuxt/config'
export async function loadNuxtConfig (argv, configContext) {
@ -24,10 +24,10 @@ export async function loadNuxtConfig (argv, configContext) {
}
// Server options
options.server = defaultsDeep({
port: argv.port || undefined,
host: argv.hostname || undefined,
socket: argv['unix-socket'] || undefined
options.server = defu({
port: argv.port || null,
host: argv.hostname || null,
socket: argv['unix-socket'] || null
}, options.server || {}, getDefaultNuxtConfig().server)
return options

View File

@ -5,6 +5,7 @@ import connect from 'connect'
import serveStatic from 'serve-static'
import compression from 'compression'
import { getNuxtConfig } from '@nuxt/config'
import { requireModule } from '@nuxt/utils'
import { showBanner } from '../utils/banner'
import * as imports from '../imports'
@ -16,7 +17,7 @@ export async function serve (cmd) {
try {
// overwrites with build config
const buildConfig = require(join(options.buildDir, 'nuxt/config.json'))
const buildConfig = requireModule(join(options.buildDir, 'nuxt/config.json'))
options.target = buildConfig.target
} catch (err) { }

View File

@ -2,7 +2,7 @@
exports[`webpack getWebpackConfig() 1`] = `
"Object {
\\"loader\\": \\"vue-loader\\",
\\"loader\\": \\"<nuxtDir>/node_modules/vue-loader/lib/index.js\\",
\\"options\\": Object {
\\"productionMode\\": true,
\\"transformAssetUrls\\": Object {
@ -24,7 +24,7 @@ exports[`webpack nuxt webpack devtool 1`] = `
exports[`webpack nuxt webpack module.rules 1`] = `
"Array [
Object {
\\"loader\\": \\"vue-loader\\",
\\"loader\\": \\"<nuxtDir>/node_modules/vue-loader/lib/index.js\\",
\\"options\\": Object {
\\"productionMode\\": true,
\\"transformAssetUrls\\": Object {
@ -90,13 +90,13 @@ exports[`webpack nuxt webpack module.rules 1`] = `
\\"resourceQuery\\": /module/,
\\"use\\": Array [
Object {
\\"loader\\": \\"vue-style-loader\\",
\\"loader\\": \\"<nuxtDir>/node_modules/vue-style-loader/index.js\\",
\\"options\\": Object {
\\"sourceMap\\": false,
},
},
Object {
\\"loader\\": \\"css-loader\\",
\\"loader\\": \\"<nuxtDir>/node_modules/css-loader/dist/cjs.js\\",
\\"options\\": Object {
\\"esModule\\": false,
\\"importLoaders\\": 2,
@ -107,7 +107,7 @@ exports[`webpack nuxt webpack module.rules 1`] = `
},
},
Object {
\\"loader\\": \\"postcss-loader\\",
\\"loader\\": \\"<nuxtDir>/node_modules/postcss-loader/src/index.js\\",
\\"options\\": Object {
\\"order\\": \\"presetEnvAndCssnanoLast\\",
\\"plugins\\": Array [
@ -124,13 +124,13 @@ exports[`webpack nuxt webpack module.rules 1`] = `
Object {
\\"use\\": Array [
Object {
\\"loader\\": \\"vue-style-loader\\",
\\"loader\\": \\"<nuxtDir>/node_modules/vue-style-loader/index.js\\",
\\"options\\": Object {
\\"sourceMap\\": false,
},
},
Object {
\\"loader\\": \\"css-loader\\",
\\"loader\\": \\"<nuxtDir>/node_modules/css-loader/dist/cjs.js\\",
\\"options\\": Object {
\\"esModule\\": false,
\\"importLoaders\\": 2,
@ -138,7 +138,7 @@ exports[`webpack nuxt webpack module.rules 1`] = `
},
},
Object {
\\"loader\\": \\"postcss-loader\\",
\\"loader\\": \\"<nuxtDir>/node_modules/postcss-loader/src/index.js\\",
\\"options\\": Object {
\\"order\\": \\"presetEnvAndCssnanoLast\\",
\\"plugins\\": Array [
@ -161,13 +161,13 @@ exports[`webpack nuxt webpack module.rules 1`] = `
\\"resourceQuery\\": /module/,
\\"use\\": Array [
Object {
\\"loader\\": \\"vue-style-loader\\",
\\"loader\\": \\"<nuxtDir>/node_modules/vue-style-loader/index.js\\",
\\"options\\": Object {
\\"sourceMap\\": false,
},
},
Object {
\\"loader\\": \\"css-loader\\",
\\"loader\\": \\"<nuxtDir>/node_modules/css-loader/dist/cjs.js\\",
\\"options\\": Object {
\\"esModule\\": false,
\\"importLoaders\\": 2,
@ -178,7 +178,7 @@ exports[`webpack nuxt webpack module.rules 1`] = `
},
},
Object {
\\"loader\\": \\"postcss-loader\\",
\\"loader\\": \\"<nuxtDir>/node_modules/postcss-loader/src/index.js\\",
\\"options\\": Object {
\\"order\\": \\"presetEnvAndCssnanoLast\\",
\\"plugins\\": Array [
@ -195,13 +195,13 @@ exports[`webpack nuxt webpack module.rules 1`] = `
Object {
\\"use\\": Array [
Object {
\\"loader\\": \\"vue-style-loader\\",
\\"loader\\": \\"<nuxtDir>/node_modules/vue-style-loader/index.js\\",
\\"options\\": Object {
\\"sourceMap\\": false,
},
},
Object {
\\"loader\\": \\"css-loader\\",
\\"loader\\": \\"<nuxtDir>/node_modules/css-loader/dist/cjs.js\\",
\\"options\\": Object {
\\"esModule\\": false,
\\"importLoaders\\": 2,
@ -209,7 +209,7 @@ exports[`webpack nuxt webpack module.rules 1`] = `
},
},
Object {
\\"loader\\": \\"postcss-loader\\",
\\"loader\\": \\"<nuxtDir>/node_modules/postcss-loader/src/index.js\\",
\\"options\\": Object {
\\"order\\": \\"presetEnvAndCssnanoLast\\",
\\"plugins\\": Array [
@ -232,13 +232,13 @@ exports[`webpack nuxt webpack module.rules 1`] = `
\\"resourceQuery\\": /module/,
\\"use\\": Array [
Object {
\\"loader\\": \\"vue-style-loader\\",
\\"loader\\": \\"<nuxtDir>/node_modules/vue-style-loader/index.js\\",
\\"options\\": Object {
\\"sourceMap\\": false,
},
},
Object {
\\"loader\\": \\"css-loader\\",
\\"loader\\": \\"<nuxtDir>/node_modules/css-loader/dist/cjs.js\\",
\\"options\\": Object {
\\"esModule\\": false,
\\"importLoaders\\": 2,
@ -249,7 +249,7 @@ exports[`webpack nuxt webpack module.rules 1`] = `
},
},
Object {
\\"loader\\": \\"postcss-loader\\",
\\"loader\\": \\"<nuxtDir>/node_modules/postcss-loader/src/index.js\\",
\\"options\\": Object {
\\"order\\": \\"presetEnvAndCssnanoLast\\",
\\"plugins\\": Array [
@ -272,13 +272,13 @@ exports[`webpack nuxt webpack module.rules 1`] = `
Object {
\\"use\\": Array [
Object {
\\"loader\\": \\"vue-style-loader\\",
\\"loader\\": \\"<nuxtDir>/node_modules/vue-style-loader/index.js\\",
\\"options\\": Object {
\\"sourceMap\\": false,
},
},
Object {
\\"loader\\": \\"css-loader\\",
\\"loader\\": \\"<nuxtDir>/node_modules/css-loader/dist/cjs.js\\",
\\"options\\": Object {
\\"esModule\\": false,
\\"importLoaders\\": 2,
@ -286,7 +286,7 @@ exports[`webpack nuxt webpack module.rules 1`] = `
},
},
Object {
\\"loader\\": \\"postcss-loader\\",
\\"loader\\": \\"<nuxtDir>/node_modules/postcss-loader/src/index.js\\",
\\"options\\": Object {
\\"order\\": \\"presetEnvAndCssnanoLast\\",
\\"plugins\\": Array [
@ -315,13 +315,13 @@ exports[`webpack nuxt webpack module.rules 1`] = `
\\"resourceQuery\\": /module/,
\\"use\\": Array [
Object {
\\"loader\\": \\"vue-style-loader\\",
\\"loader\\": \\"<nuxtDir>/node_modules/vue-style-loader/index.js\\",
\\"options\\": Object {
\\"sourceMap\\": false,
},
},
Object {
\\"loader\\": \\"css-loader\\",
\\"loader\\": \\"<nuxtDir>/node_modules/css-loader/dist/cjs.js\\",
\\"options\\": Object {
\\"esModule\\": false,
\\"importLoaders\\": 2,
@ -332,7 +332,7 @@ exports[`webpack nuxt webpack module.rules 1`] = `
},
},
Object {
\\"loader\\": \\"postcss-loader\\",
\\"loader\\": \\"<nuxtDir>/node_modules/postcss-loader/src/index.js\\",
\\"options\\": Object {
\\"order\\": \\"presetEnvAndCssnanoLast\\",
\\"plugins\\": Array [
@ -345,7 +345,7 @@ exports[`webpack nuxt webpack module.rules 1`] = `
},
},
Object {
\\"loader\\": \\"sass-loader\\",
\\"loader\\": \\"<nuxtDir>/node_modules/sass-loader/dist/cjs.js\\",
\\"options\\": Object {
\\"sassOptions\\": Object {
\\"indentedSyntax\\": true,
@ -358,13 +358,13 @@ exports[`webpack nuxt webpack module.rules 1`] = `
Object {
\\"use\\": Array [
Object {
\\"loader\\": \\"vue-style-loader\\",
\\"loader\\": \\"<nuxtDir>/node_modules/vue-style-loader/index.js\\",
\\"options\\": Object {
\\"sourceMap\\": false,
},
},
Object {
\\"loader\\": \\"css-loader\\",
\\"loader\\": \\"<nuxtDir>/node_modules/css-loader/dist/cjs.js\\",
\\"options\\": Object {
\\"esModule\\": false,
\\"importLoaders\\": 2,
@ -372,7 +372,7 @@ exports[`webpack nuxt webpack module.rules 1`] = `
},
},
Object {
\\"loader\\": \\"postcss-loader\\",
\\"loader\\": \\"<nuxtDir>/node_modules/postcss-loader/src/index.js\\",
\\"options\\": Object {
\\"order\\": \\"presetEnvAndCssnanoLast\\",
\\"plugins\\": Array [
@ -385,7 +385,7 @@ exports[`webpack nuxt webpack module.rules 1`] = `
},
},
Object {
\\"loader\\": \\"sass-loader\\",
\\"loader\\": \\"<nuxtDir>/node_modules/sass-loader/dist/cjs.js\\",
\\"options\\": Object {
\\"sassOptions\\": Object {
\\"indentedSyntax\\": true,
@ -404,13 +404,13 @@ exports[`webpack nuxt webpack module.rules 1`] = `
\\"resourceQuery\\": /module/,
\\"use\\": Array [
Object {
\\"loader\\": \\"vue-style-loader\\",
\\"loader\\": \\"<nuxtDir>/node_modules/vue-style-loader/index.js\\",
\\"options\\": Object {
\\"sourceMap\\": false,
},
},
Object {
\\"loader\\": \\"css-loader\\",
\\"loader\\": \\"<nuxtDir>/node_modules/css-loader/dist/cjs.js\\",
\\"options\\": Object {
\\"esModule\\": false,
\\"importLoaders\\": 2,
@ -421,7 +421,7 @@ exports[`webpack nuxt webpack module.rules 1`] = `
},
},
Object {
\\"loader\\": \\"postcss-loader\\",
\\"loader\\": \\"<nuxtDir>/node_modules/postcss-loader/src/index.js\\",
\\"options\\": Object {
\\"order\\": \\"presetEnvAndCssnanoLast\\",
\\"plugins\\": Array [
@ -434,7 +434,7 @@ exports[`webpack nuxt webpack module.rules 1`] = `
},
},
Object {
\\"loader\\": \\"sass-loader\\",
\\"loader\\": \\"<nuxtDir>/node_modules/sass-loader/dist/cjs.js\\",
\\"options\\": Object {
\\"sourceMap\\": false,
},
@ -444,13 +444,13 @@ exports[`webpack nuxt webpack module.rules 1`] = `
Object {
\\"use\\": Array [
Object {
\\"loader\\": \\"vue-style-loader\\",
\\"loader\\": \\"<nuxtDir>/node_modules/vue-style-loader/index.js\\",
\\"options\\": Object {
\\"sourceMap\\": false,
},
},
Object {
\\"loader\\": \\"css-loader\\",
\\"loader\\": \\"<nuxtDir>/node_modules/css-loader/dist/cjs.js\\",
\\"options\\": Object {
\\"esModule\\": false,
\\"importLoaders\\": 2,
@ -458,7 +458,7 @@ exports[`webpack nuxt webpack module.rules 1`] = `
},
},
Object {
\\"loader\\": \\"postcss-loader\\",
\\"loader\\": \\"<nuxtDir>/node_modules/postcss-loader/src/index.js\\",
\\"options\\": Object {
\\"order\\": \\"presetEnvAndCssnanoLast\\",
\\"plugins\\": Array [
@ -471,7 +471,7 @@ exports[`webpack nuxt webpack module.rules 1`] = `
},
},
Object {
\\"loader\\": \\"sass-loader\\",
\\"loader\\": \\"<nuxtDir>/node_modules/sass-loader/dist/cjs.js\\",
\\"options\\": Object {
\\"sourceMap\\": false,
},
@ -487,13 +487,13 @@ exports[`webpack nuxt webpack module.rules 1`] = `
\\"resourceQuery\\": /module/,
\\"use\\": Array [
Object {
\\"loader\\": \\"vue-style-loader\\",
\\"loader\\": \\"<nuxtDir>/node_modules/vue-style-loader/index.js\\",
\\"options\\": Object {
\\"sourceMap\\": false,
},
},
Object {
\\"loader\\": \\"css-loader\\",
\\"loader\\": \\"<nuxtDir>/node_modules/css-loader/dist/cjs.js\\",
\\"options\\": Object {
\\"esModule\\": false,
\\"importLoaders\\": 2,
@ -504,7 +504,7 @@ exports[`webpack nuxt webpack module.rules 1`] = `
},
},
Object {
\\"loader\\": \\"postcss-loader\\",
\\"loader\\": \\"<nuxtDir>/node_modules/postcss-loader/src/index.js\\",
\\"options\\": Object {
\\"order\\": \\"presetEnvAndCssnanoLast\\",
\\"plugins\\": Array [
@ -527,13 +527,13 @@ exports[`webpack nuxt webpack module.rules 1`] = `
Object {
\\"use\\": Array [
Object {
\\"loader\\": \\"vue-style-loader\\",
\\"loader\\": \\"<nuxtDir>/node_modules/vue-style-loader/index.js\\",
\\"options\\": Object {
\\"sourceMap\\": false,
},
},
Object {
\\"loader\\": \\"css-loader\\",
\\"loader\\": \\"<nuxtDir>/node_modules/css-loader/dist/cjs.js\\",
\\"options\\": Object {
\\"esModule\\": false,
\\"importLoaders\\": 2,
@ -541,7 +541,7 @@ exports[`webpack nuxt webpack module.rules 1`] = `
},
},
Object {
\\"loader\\": \\"postcss-loader\\",
\\"loader\\": \\"<nuxtDir>/node_modules/postcss-loader/src/index.js\\",
\\"options\\": Object {
\\"order\\": \\"presetEnvAndCssnanoLast\\",
\\"plugins\\": Array [
@ -568,7 +568,7 @@ exports[`webpack nuxt webpack module.rules 1`] = `
\\"test\\": /\\\\.(png|jpe?g|gif|svg|webp|avif)$/i,
\\"use\\": Array [
Object {
\\"loader\\": \\"url-loader\\",
\\"loader\\": \\"<nuxtDir>/node_modules/url-loader/dist/cjs.js\\",
\\"options\\": Object {
\\"esModule\\": false,
\\"limit\\": 1000,
@ -581,7 +581,7 @@ exports[`webpack nuxt webpack module.rules 1`] = `
\\"test\\": /\\\\.(woff2?|eot|ttf|otf)(\\\\?.*)?$/i,
\\"use\\": Array [
Object {
\\"loader\\": \\"url-loader\\",
\\"loader\\": \\"<nuxtDir>/node_modules/url-loader/dist/cjs.js\\",
\\"options\\": Object {
\\"esModule\\": false,
\\"limit\\": 1000,
@ -594,7 +594,7 @@ exports[`webpack nuxt webpack module.rules 1`] = `
\\"test\\": /\\\\.(webm|mp4|ogv)$/i,
\\"use\\": Array [
Object {
\\"loader\\": \\"file-loader\\",
\\"loader\\": \\"<nuxtDir>/node_modules/file-loader/dist/cjs.js\\",
\\"options\\": Object {
\\"esModule\\": false,
\\"name\\": \\"videos/[name].[contenthash:7].[ext]\\",
@ -608,7 +608,7 @@ exports[`webpack nuxt webpack module.rules 1`] = `
exports[`webpack nuxt webpack module.rules loader=.*-loader 1`] = `
"Object {
\\"loader\\": \\"vue-loader\\",
\\"loader\\": \\"<nuxtDir>/node_modules/vue-loader/lib/index.js\\",
\\"options\\": Object {
\\"productionMode\\": true,
\\"transformAssetUrls\\": Object {
@ -625,7 +625,7 @@ exports[`webpack nuxt webpack module.rules loader=.*-loader 1`] = `
exports[`webpack nuxt webpack module.rules loader=vue- 1`] = `
"Object {
\\"loader\\": \\"vue-loader\\",
\\"loader\\": \\"<nuxtDir>/node_modules/vue-loader/lib/index.js\\",
\\"options\\": Object {
\\"productionMode\\": true,
\\"transformAssetUrls\\": Object {

View File

@ -17,8 +17,8 @@
"defu": "^3.2.2",
"destr": "^1.0.1",
"dotenv": "^8.2.0",
"esm": "^3.2.25",
"jiti": "^0.1.17",
"lodash": "^4.17.20",
"rc9": "^1.2.0",
"std-env": "^2.2.1"
},

View File

@ -1,4 +1,4 @@
import capitalize from 'lodash/capitalize'
import { capitalize } from 'lodash'
import env from 'std-env'
import { TARGETS } from '@nuxt/utils'

View File

@ -4,28 +4,28 @@ import defu from 'defu'
import consola from 'consola'
import dotenv from 'dotenv'
import { clearRequireCache, scanRequireTree } from '@nuxt/utils'
import esm from 'esm'
import jiti from 'jiti'
import _createRequire from 'create-require'
import destr from 'destr'
import * as rc from 'rc9'
import { defaultNuxtConfigFile } from './config'
const isJest = typeof jest !== 'undefined'
const _require = isJest ? _createRequire(__filename) : jiti(__filename)
export async function loadNuxtConfig ({
rootDir = '.',
envConfig = {},
configFile = defaultNuxtConfigFile,
configContext = {},
configOverrides = {},
createRequire = module => isJest ? _createRequire(module.filename) : esm(module, { cache: false })
configOverrides = {}
} = {}) {
rootDir = path.resolve(rootDir)
let options = {}
try {
configFile = require.resolve(path.resolve(rootDir, configFile))
configFile = _require.resolve(path.resolve(rootDir, configFile))
} catch (e) {
if (e.code !== 'MODULE_NOT_FOUND') {
throw (e)
@ -56,7 +56,6 @@ export async function loadNuxtConfig ({
if (configFile) {
// Clear cache
clearRequireCache(configFile)
const _require = createRequire(module)
options = _require(configFile) || {}
if (options.default) {
options = options.default

View File

@ -1,9 +1,7 @@
import path from 'path'
import fs from 'fs'
import defaultsDeep from 'lodash/defaultsDeep'
import { defaultsDeep, pick, uniq } from 'lodash'
import defu from 'defu'
import pick from 'lodash/pick'
import uniq from 'lodash/uniq'
import consola from 'consola'
import destr from 'destr'
import { TARGETS, MODES, guardDir, isNonEmptyString, isPureObject, isUrl, getMainModule, urlJoin, getPKG } from '@nuxt/utils'
@ -465,20 +463,22 @@ export function getNuxtConfig (_options) {
staticAssets.versionBase = urlJoin(staticAssets.base, staticAssets.version)
}
// createRequire factory
if (options.createRequire === undefined) {
const isJest = typeof jest !== 'undefined'
options.createRequire = isJest ? false : 'esm'
}
if (options.createRequire === 'esm') {
const esm = require('esm')
options.createRequire = module => esm(module, { cache: false })
// createRequire
const isJest = typeof jest !== 'undefined'
const defaultCreateRequire = isJest ? 'native' : 'jiti'
options.createRequire = process.env.NUXT_CREATE_REQUIRE || options.createRequire || defaultCreateRequire
if (options.createRequire === 'native') {
const createRequire = require('create-require')
options.createRequire = p => createRequire(typeof p === 'string' ? p : p.filename)
} else if (options.createRequire === 'jiti') {
const jiti = require('jiti')
options.createRequire = module => jiti(module.filename)
options.createRequire = p => jiti(typeof p === 'string' ? p : p.filename)
} else if (typeof options.createRequire !== 'function') {
const createRequire = require('create-require')
options.createRequire = module => createRequire(module.filename)
throw new TypeError(
`Unsupported createRequire value ${options.createRequire}! Possible values: "native", "jiti", <Function>`
)
}
// Indicator

View File

@ -9,17 +9,14 @@
],
"dependencies": {
"@nuxt/config": "2.14.12",
"@nuxt/devalue": "^1.2.4",
"@nuxt/server": "2.14.12",
"@nuxt/utils": "2.14.12",
"@nuxt/vue-renderer": "2.14.12",
"consola": "^2.15.0",
"debug": "^4.2.0",
"esm": "^3.2.25",
"create-require": "^1.1.1",
"fs-extra": "^9.0.1",
"hable": "^3.0.0",
"hash-sum": "^2.0.0",
"std-env": "^2.2.1"
"lodash": "^4.17.20"
},
"publishConfig": {
"access": "public"

View File

@ -121,11 +121,13 @@ export default class ModuleContainer {
)
}
requireModule (moduleOpts) {
return this.addModule(moduleOpts)
requireModule (moduleOpts, { requirePath } = {}) {
return this.addModule(moduleOpts, undefined, { requirePath })
}
async addModule (moduleOpts) {
async addModule (moduleOpts, arg2, arg3) {
// Arg2 was previously used for requireOnce which is ignored now
const { requirePath } = { ...arg2, ...arg3 }
let src
let options
let handler
@ -154,7 +156,7 @@ export default class ModuleContainer {
// Resolve handler
if (!handler) {
try {
handler = this.nuxt.resolver.requireModule(src, { useESM: true })
handler = this.nuxt.resolver.requireModule(src, { requirePath })
} catch (error) {
if (error.code !== 'MODULE_NOT_FOUND') {
throw error

View File

@ -1,5 +1,5 @@
import isPlainObject from 'lodash/isPlainObject'
import { isPlainObject } from 'lodash'
import consola from 'consola'
import Hookable from 'hable'

View File

@ -1,6 +1,7 @@
import { resolve, join } from 'path'
import fs from 'fs-extra'
import consola from 'consola'
import createRequire from 'create-require'
import {
startsWithRootAlias,
@ -20,23 +21,20 @@ export default class Resolver {
this.resolveModule = this.resolveModule.bind(this)
this.requireModule = this.requireModule.bind(this)
const { createRequire } = this.options
this._require = createRequire ? createRequire(module) : module.require
this._resolve = require.resolve
this._createRequire = this.options.createRequire || createRequire
this._require = this._createRequire(__filename)
}
resolveModule (path) {
resolveModule (path, { requirePath } = {}) {
try {
return this._resolve(path, {
paths: this.options.modulesDir
return this._require.resolve(path, {
paths: [
requirePath || __dirname,
...[].concat(this.options.modulesDir)
]
})
} catch (error) {
if (error.code !== 'MODULE_NOT_FOUND') {
// TODO: remove after https://github.com/facebook/jest/pull/8487 released
if (process.env.NODE_ENV === 'test' && error.message.startsWith('Cannot resolve module')) {
return
}
throw error
}
}
@ -54,7 +52,7 @@ export default class Resolver {
return resolve(this.options.srcDir, path)
}
resolvePath (path, { alias, isAlias = alias, module, isModule = module, isStyle } = {}) {
resolvePath (path, { alias, isAlias = alias, module, isModule = module, isStyle, requirePath } = {}) {
// TODO: Remove in Nuxt 3
if (alias) {
consola.warn('Using alias is deprecated and will be removed in Nuxt 3. Use `isAlias` instead.')
@ -72,7 +70,7 @@ export default class Resolver {
// Try to resolve it as a regular module
if (isModule !== false) {
resolvedPath = this.resolveModule(path)
resolvedPath = this.resolveModule(path, { requirePath })
}
// Try to resolve alias
@ -119,7 +117,7 @@ export default class Resolver {
throw new Error(`Cannot resolve "${path}" from "${resolvedPath}"`)
}
requireModule (path, { esm, useESM = esm, alias, isAlias = alias, intropDefault, interopDefault = intropDefault } = {}) {
requireModule (path, { alias, isAlias = alias, intropDefault, interopDefault = intropDefault, requirePath } = {}) {
let resolvedPath = path
let requiredModule
@ -130,15 +128,12 @@ export default class Resolver {
if (alias) {
consola.warn('Using alias is deprecated and will be removed in Nuxt 3. Use `isAlias` instead.')
}
if (esm) {
consola.warn('Using esm is deprecated and will be removed in Nuxt 3. Use `useESM` instead.')
}
let lastError
// Try to resolve path
try {
resolvedPath = this.resolvePath(path, { isAlias })
resolvedPath = this.resolvePath(path, { isAlias, requirePath })
} catch (e) {
lastError = e
}
@ -151,18 +146,10 @@ export default class Resolver {
clearRequireCache(resolvedPath)
}
// By default use esm only for js,mjs files outside of node_modules
if (useESM === undefined) {
useESM = !isExternal && /.(js|mjs)$/.test(resolvedPath)
}
// Try to require
try {
if (useESM) {
requiredModule = this._require(resolvedPath)
} else {
requiredModule = require(resolvedPath)
}
const _require = requirePath ? this._createRequire(requirePath) : this._require
requiredModule = _require(resolvedPath)
} catch (e) {
lastError = e
}

View File

@ -318,7 +318,7 @@ describe('core: module', () => {
module.requireModule(moduleOpts)
expect(module.addModule).toBeCalledTimes(1)
expect(module.addModule).toBeCalledWith(moduleOpts)
expect(module.addModule).toBeCalledWith(moduleOpts, undefined, { requirePath: undefined })
})
test('should add string module', async () => {
@ -332,7 +332,7 @@ describe('core: module', () => {
const result = await module.addModule('moduleTest')
expect(requireModule).toBeCalledTimes(1)
expect(requireModule).toBeCalledWith('moduleTest', { useESM: true })
expect(requireModule).toBeCalledWith('moduleTest', { requirePath: undefined })
expect(module.requiredModules).toEqual({
moduleTest: {
handler: expect.any(Function),
@ -381,7 +381,7 @@ describe('core: module', () => {
const result = await module.addModule(['moduleTest', { test: true }])
expect(requireModule).toBeCalledTimes(1)
expect(requireModule).toBeCalledWith('moduleTest', { useESM: true })
expect(requireModule).toBeCalledWith('moduleTest', { requirePath: undefined })
expect(module.requiredModules).toEqual({
moduleTest: {
handler: expect.any(Function),

View File

@ -5,13 +5,14 @@ import { startsWithRootAlias, startsWithSrcAlias } from '@nuxt/utils'
import Resolver from '../src/resolver'
jest.mock('esm', () => jest.fn(() => jest.fn()))
jest.mock('fs-extra')
jest.mock('@nuxt/utils')
jest.spyOn(path, 'join')
jest.spyOn(path, 'resolve')
const modulesDir = path.resolve(__dirname, './__modules__')
describe.posix('core: resolver', () => {
beforeEach(() => {
jest.clearAllMocks()
@ -33,40 +34,22 @@ describe.posix('core: resolver', () => {
test('should call require.resolve in resolveModule', () => {
const resolver = new Resolver({
options: { modulesDir: '/var/nuxt/node_modules' }
options: { modulesDir }
})
const resolve = resolver._resolve = jest.fn(() => '/var/nuxt/resolver/module')
const modulePath = resolver.resolveModule('/var/nuxt/resolver')
const modulePath = resolver.resolveModule('__resolver__')
expect(modulePath).toEqual('/var/nuxt/resolver/module')
expect(resolve).toBeCalledTimes(1)
expect(resolve).toBeCalledWith('/var/nuxt/resolver', { paths: '/var/nuxt/node_modules' })
expect(modulePath).toEqual(path.resolve(modulesDir, './__resolver__.js'))
})
test('should return undefined when module is not found', () => {
const resolver = new Resolver({
options: { modulesDir: '/var/nuxt/node_modules' }
})
const resolve = resolver._resolve = jest.fn(() => {
const err = new Error()
err.code = 'MODULE_NOT_FOUND'
throw err
options: { modulesDir }
})
const modulePath = resolver.resolveModule('/var/nuxt/resolver')
const modulePath = resolver.resolveModule('non-exist-module')
expect(modulePath).toBeUndefined()
expect(resolve).toBeCalledTimes(1)
})
test('should throw error when require.resolve failed', () => {
const resolver = new Resolver({
options: { modulesDir: '/var/nuxt/node_modules' }
})
resolver._resolve = jest.fn(() => { throw new Error('resolve failed') })
expect(() => resolver.resolveModule('/var/nuxt/resolver')).toThrow('resolve failed')
})
test('should resolve root alias', () => {
@ -380,18 +363,6 @@ describe.posix('core: resolver', () => {
expect(resolvedModule).toEqual({ default: 'resolved module' })
})
test('should require common module', () => {
const resolver = new Resolver({
options: {}
})
resolver.resolvePath = jest.fn(() => 'path')
resolver._require = jest.fn(() => ({ default: 'resolved module' }))
const resolvedModule = resolver.requireModule('path', { useESM: false })
expect(resolvedModule).toBe(path)
})
test('should throw error if resolvePath failed', () => {
const resolver = new Resolver({
options: {}
@ -444,11 +415,6 @@ describe.posix('core: resolver', () => {
})
resolver.resolvePath = jest.fn().mockReturnValue('/var/nuxt/resolver/file.js')
resolver._require = jest.fn()
resolver.requireModule('/var/nuxt/resolver/file.js', { esm: true })
const warnMsg = 'Using esm is deprecated and will be removed in Nuxt 3. Use `useESM` instead.'
expect(consola.warn).toBeCalledTimes(1)
expect(consola.warn).toBeCalledWith(warnMsg)
})
})
})

View File

@ -11,6 +11,7 @@
"@nuxt/utils": "2.14.12",
"chalk": "^4.1.0",
"consola": "^2.15.0",
"defu": "^3.2.2",
"devalue": "^2.0.1",
"fs-extra": "^9.0.1",
"html-minifier": "^4.0.0",

View File

@ -7,7 +7,7 @@ import defu from 'defu'
import htmlMinifier from 'html-minifier'
import { parse } from 'node-html-parser'
import { isFullStatic, flatRoutes, isString, isUrl, promisifyRoute, urlJoin, waitFor } from '@nuxt/utils'
import { isFullStatic, flatRoutes, isString, isUrl, promisifyRoute, urlJoin, waitFor, requireModule } from '@nuxt/utils'
export default class Generator {
constructor (nuxt, builder) {
@ -153,14 +153,14 @@ export default class Generator {
getBuildConfig () {
try {
return require(path.join(this.options.buildDir, 'nuxt/config.json'))
return requireModule(path.join(this.options.buildDir, 'nuxt/config.json'))
} catch (err) {
return null
}
}
getAppRoutes () {
return require(path.join(this.options.buildDir, 'routes.json'))
return requireModule(path.join(this.options.buildDir, 'routes.json'))
}
async generateRoutes (routes) {
@ -382,8 +382,9 @@ export default class Generator {
let fileName
if (this.options.generate.subFolders) {
fileName = path.join(route, path.sep, 'index.html') // /about -> /about/index.html
fileName = fileName === '/404/index.html' ? '/404.html' : fileName // /404 -> /404.html
fileName = route === '/404'
? path.join(path.sep, '404.html') // /404 -> /404.html
: path.join(route, path.sep, 'index.html') // /about -> /about/index.html
} else {
const normalizedRoute = route.replace(/\/$/, '')
fileName = route.length > 1 ? path.join(path.sep, normalizedRoute + '.html') : path.join(path.sep, 'index.html')

View File

@ -1,3 +1,10 @@
import { resolve } from 'path'
import env from 'std-env'
const isWin = env.windows
const rootDir = isWin ? 'C:\\nuxt' : '/var/nuxt'
export const createNuxt = () => ({
ready: jest.fn(),
callHook: jest.fn(),
@ -6,11 +13,11 @@ export const createNuxt = () => ({
},
options: {
mode: 'universal',
srcDir: '/var/nuxt/src',
buildDir: '/var/nuxt/build',
generate: { dir: '/var/nuxt/generate' },
srcDir: resolve(rootDir, 'src'),
buildDir: resolve(rootDir, 'build'),
generate: { dir: resolve(rootDir, 'generate') },
build: { publicPath: '__public' },
dir: { static: '/var/nuxt/static' },
dir: { static: resolve(rootDir, 'static') },
render: {}
}
})

View File

@ -1,4 +1,3 @@
import path from 'path'
import chalk from 'chalk'
import consola from 'consola'
import fsExtra from 'fs-extra'
@ -7,7 +6,6 @@ import { waitFor } from '@nuxt/utils'
import Generator from '../src/generator'
import { createNuxt } from './__utils__'
jest.mock('path')
jest.mock('chalk', () => ({
red: jest.fn(str => `red:${str}`),
yellow: jest.fn(str => `yellow:${str}`),
@ -17,17 +15,6 @@ jest.mock('fs-extra')
jest.mock('@nuxt/utils')
describe('generator: generate routes', () => {
const sep = path.sep
beforeAll(() => {
path.sep = '[sep]'
path.join.mockImplementation((...args) => `join(${args.join(', ')})`)
})
afterAll(() => {
path.sep = sep
})
beforeEach(() => {
jest.clearAllMocks()
})
@ -147,25 +134,28 @@ grey:bar failed`)
const nuxt = createNuxt()
nuxt.options.generate.fallback = 'fallback.html'
const generator = new Generator(nuxt)
path.join.mockClear()
fsExtra.exists.mockReturnValueOnce(false)
await generator.afterGenerate()
expect(path.join).toBeCalledTimes(1)
expect(path.join).toBeCalledWith(generator.distPath, 'fallback.html')
expect(fsExtra.exists).toBeCalledTimes(1)
expect(fsExtra.exists).toBeCalledWith(`join(${generator.distPath}, fallback.html)`)
expect(fsExtra.exists.mock.calls[0][0]).toBePath(
'/var/nuxt/generate/fallback.html',
'C:\\nuxt\\generate\\fallback.html'
)
expect(nuxt.server.renderRoute).toBeCalledTimes(1)
expect(nuxt.server.renderRoute).toBeCalledWith('/', { spa: true })
expect(fsExtra.writeFile).toBeCalledTimes(1)
expect(fsExtra.writeFile).toBeCalledWith(`join(${generator.distPath}, fallback.html)`, 'rendered html', 'utf8')
expect(fsExtra.writeFile).toBeCalledWith(expect.any(String), 'rendered html', 'utf8')
expect(fsExtra.writeFile.mock.calls[0][0]).toBePath(
'/var/nuxt/generate/fallback.html',
'C:\\nuxt\\generate\\fallback.html'
)
})
test('should disable writing fallback if fallback is empty or not string', async () => {
const nuxt = createNuxt()
const generator = new Generator(nuxt)
path.join.mockClear()
nuxt.options.generate.fallback = ''
await generator.afterGenerate()
@ -173,7 +163,6 @@ grey:bar failed`)
nuxt.options.generate.fallback = jest.fn()
await generator.afterGenerate()
expect(path.join).not.toBeCalled()
expect(fsExtra.exists).not.toBeCalled()
expect(nuxt.server.renderRoute).not.toBeCalled()
expect(fsExtra.writeFile).not.toBeCalled()
@ -183,15 +172,15 @@ grey:bar failed`)
const nuxt = createNuxt()
nuxt.options.generate.fallback = 'fallback.html'
const generator = new Generator(nuxt)
path.join.mockClear()
fsExtra.exists.mockReturnValueOnce(true)
await generator.afterGenerate()
expect(path.join).toBeCalledTimes(1)
expect(path.join).toBeCalledWith(generator.distPath, 'fallback.html')
expect(fsExtra.exists).toBeCalledTimes(1)
expect(fsExtra.exists).toBeCalledWith(`join(${generator.distPath}, fallback.html)`)
expect(fsExtra.exists.mock.calls[0][0]).toBePath(
'/var/nuxt/generate/fallback.html',
'C:\\nuxt\\generate\\fallback.html'
)
expect(nuxt.server.renderRoute).not.toBeCalled()
expect(fsExtra.writeFile).not.toBeCalled()
})
@ -199,7 +188,6 @@ grey:bar failed`)
test('should disable writing fallback if fallback is empty or not string', async () => {
const nuxt = createNuxt()
const generator = new Generator(nuxt)
path.join.mockClear()
nuxt.options.generate.fallback = ''
await generator.afterGenerate()
@ -207,7 +195,6 @@ grey:bar failed`)
nuxt.options.generate.fallback = jest.fn()
await generator.afterGenerate()
expect(path.join).not.toBeCalled()
expect(fsExtra.exists).not.toBeCalled()
expect(fsExtra.writeFile).not.toBeCalled()
})

View File

@ -1,4 +1,3 @@
import path from 'path'
import consola from 'consola'
import fsExtra from 'fs-extra'
import { flatRoutes, isString, isUrl, promisifyRoute } from '@nuxt/utils'
@ -6,15 +5,12 @@ import { flatRoutes, isString, isUrl, promisifyRoute } from '@nuxt/utils'
import Generator from '../src/generator'
import { createNuxt, hookCalls } from './__utils__'
jest.mock('path')
jest.mock('fs-extra')
jest.mock('@nuxt/utils')
describe('generator: initialize', () => {
beforeAll(() => {
isString.mockImplementation(str => typeof str === 'string')
path.join.mockImplementation((...args) => `join(${args.join(', ')})`)
path.resolve.mockImplementation((...args) => `resolve(${args.join(', ')})`)
})
beforeEach(() => {
@ -34,10 +30,22 @@ describe('generator: initialize', () => {
expect(generator.nuxt).toBe(nuxt)
expect(generator.options).toBe(nuxt.options)
expect(generator.builder).toBe(builder)
expect(generator.staticRoutes).toEqual('resolve(/var/nuxt/src, /var/nuxt/static)')
expect(generator.srcBuiltPath).toBe('resolve(/var/nuxt/build, dist, client)')
expect(generator.distPath).toBe('/var/nuxt/generate')
expect(generator.distNuxtPath).toBe('join(/var/nuxt/generate, )')
expect(generator.staticRoutes).toBePath(
'/var/nuxt/static',
'C:\\nuxt\\static'
)
expect(generator.srcBuiltPath).toBePath(
'/var/nuxt/build/dist/client',
'C:\\nuxt\\build\\dist\\client'
)
expect(generator.distPath).toBePath(
'/var/nuxt/generate',
'C:\\nuxt\\generate'
)
expect(generator.distNuxtPath).toBePath(
'/var/nuxt/generate',
'C:\\nuxt\\generate'
)
})
test('should append publicPath to distPath if publicPath is not url', () => {
@ -50,7 +58,10 @@ describe('generator: initialize', () => {
const builder = jest.fn()
const generator = new Generator(nuxt, builder)
expect(generator.distNuxtPath).toBe('join(/var/nuxt/generate, __public)')
expect(generator.distNuxtPath).toBePath(
'/var/nuxt/generate/__public',
'C:\\nuxt\\generate\\__public'
)
})
test('should initiate with build and init by default', async () => {
@ -172,8 +183,6 @@ describe('generator: initialize', () => {
const nuxt = createNuxt()
nuxt.options.generate.fallback = 'fallback.html'
const generator = new Generator(nuxt)
path.join.mockClear()
path.resolve.mockClear()
fsExtra.exists.mockReturnValueOnce(false)
await generator.initDist()
@ -185,10 +194,11 @@ describe('generator: initialize', () => {
expect(fsExtra.exists).toBeCalledWith(generator.staticRoutes)
expect(fsExtra.copy).toBeCalledTimes(1)
expect(fsExtra.copy).toBeCalledWith(generator.srcBuiltPath, generator.distNuxtPath)
expect(path.resolve).toBeCalledTimes(1)
expect(path.resolve).toBeCalledWith(generator.distPath, '.nojekyll')
expect(fsExtra.writeFile).toBeCalledTimes(1)
expect(fsExtra.writeFile).toBeCalledWith(`resolve(${generator.distPath}, .nojekyll)`, '')
expect(fsExtra.writeFile.mock.calls[0][0]).toBePath(
'/var/nuxt/generate/.nojekyll',
'C:\\nuxt\\generate\\.nojekyll'
)
expect(hookCalls(nuxt, 'generate:distCopied')[0][0]).toMatchObject(generator)
})

View File

@ -1,4 +1,3 @@
import path from 'path'
import consola from 'consola'
import fsExtra from 'fs-extra'
import htmlMinifier from 'html-minifier'
@ -6,24 +5,11 @@ import htmlMinifier from 'html-minifier'
import Generator from '../src/generator'
import { createNuxt, hookCalls } from './__utils__'
jest.mock('path')
jest.mock('fs-extra')
jest.mock('html-minifier')
jest.mock('@nuxt/utils')
describe('generator: generate route', () => {
const sep = path.sep
beforeAll(() => {
path.sep = '[sep]'
path.join.mockImplementation((...args) => `join(${args.join(', ')})`)
path.dirname.mockImplementation((...args) => `dirname(${args.join(', ')})`)
})
afterAll(() => {
path.sep = sep
})
beforeEach(() => {
jest.clearAllMocks()
})
@ -34,7 +20,6 @@ describe('generator: generate route', () => {
nuxt.options.generate.minify = undefined
nuxt.options.generate.subFolders = false
const generator = new Generator(nuxt)
path.join.mockClear()
const route = '/foo/'
const payload = {}
@ -44,26 +29,38 @@ describe('generator: generate route', () => {
expect(nuxt.server.renderRoute).toBeCalledTimes(1)
expect(nuxt.server.renderRoute).toBeCalledWith(route, { payload })
expect(path.join).toBeCalledTimes(2)
expect(path.join).nthCalledWith(1, '[sep]', '/foo.html')
expect(path.join).nthCalledWith(2, generator.distPath, 'join([sep], /foo.html)')
expect(hookCalls(nuxt, 'generate:page')[0][0]).toMatchObject({
const genernatePageHookCall = hookCalls(nuxt, 'generate:page')[0][0]
expect(genernatePageHookCall).toMatchObject({
route,
html: 'rendered html',
path: `join(${generator.distPath}, join([sep], /foo.html))`
html: 'rendered html'
})
expect(genernatePageHookCall.path).toBePath(
'/var/nuxt/generate/foo.html',
'C:\\nuxt\\generate\\foo.html'
)
expect(hookCalls(nuxt, 'generate:routeCreated')[0][0]).toMatchObject({
const genernateRouteCreatedHookCall = hookCalls(nuxt, 'generate:routeCreated')[0][0]
expect(genernateRouteCreatedHookCall).toMatchObject({
route,
errors: [],
path: `join(${generator.distPath}, join([sep], /foo.html))`
errors: []
})
expect(genernateRouteCreatedHookCall.path).toBePath(
'/var/nuxt/generate/foo.html',
'C:\\nuxt\\generate\\foo.html'
)
expect(fsExtra.mkdirp).toBeCalledTimes(1)
expect(fsExtra.mkdirp).toBeCalledWith(`dirname(join(${generator.distPath}, join([sep], /foo.html)))`)
expect(fsExtra.mkdirp.mock.calls[0][0]).toBePath(
'/var/nuxt/generate',
'C:\\nuxt\\generate'
)
expect(fsExtra.writeFile).toBeCalledTimes(1)
expect(fsExtra.writeFile).toBeCalledWith(`join(${generator.distPath}, join([sep], /foo.html))`, 'rendered html', 'utf8')
expect(fsExtra.writeFile).toBeCalledWith(expect.any(String), 'rendered html', 'utf8')
expect(fsExtra.writeFile.mock.calls[0][0]).toBePath(
'/var/nuxt/generate/foo.html',
'C:\\nuxt\\generate\\foo.html'
)
expect(returned).toEqual(true)
})
@ -158,7 +155,11 @@ describe('generator: generate route', () => {
expect(htmlMinifier.minify).toBeCalledTimes(1)
expect(htmlMinifier.minify).toBeCalledWith('rendered html', { value: 'test-minify' })
expect(fsExtra.writeFile).toBeCalledTimes(1)
expect(fsExtra.writeFile).toBeCalledWith(`join(${generator.distPath}, join([sep], /foo.html))`, 'minified rendered html', 'utf8')
expect(fsExtra.writeFile).toBeCalledWith(expect.any(String), 'minified rendered html', 'utf8')
expect(fsExtra.writeFile.mock.calls[0][0]).toBePath(
'/var/nuxt/generate/foo.html',
'C:\\nuxt\\generate\\foo.html'
)
expect(returned).toEqual(true)
})
@ -191,17 +192,17 @@ describe('generator: generate route', () => {
nuxt.options.build.html = { minify: false }
nuxt.options.generate.subFolders = true
const generator = new Generator(nuxt)
path.join.mockClear()
const route = '/foo'
const returned = await generator.generateRoute({ route })
expect(path.join).toBeCalledTimes(2)
expect(path.join).nthCalledWith(1, route, '[sep]', 'index.html')
expect(path.join).nthCalledWith(2, generator.distPath, 'join(/foo, [sep], index.html)')
expect(fsExtra.writeFile).toBeCalledTimes(1)
expect(fsExtra.writeFile).toBeCalledWith(`join(${generator.distPath}, join(/foo, [sep], index.html))`, 'rendered html', 'utf8')
expect(fsExtra.writeFile).toBeCalledWith(expect.any(String), 'rendered html', 'utf8')
expect(fsExtra.writeFile.mock.calls[0][0]).toBePath(
'/var/nuxt/generate/foo/index.html',
'C:\\nuxt\\generate\\foo\\index.html'
)
expect(returned).toEqual(true)
})
@ -210,18 +211,17 @@ describe('generator: generate route', () => {
nuxt.options.build.html = { minify: false }
nuxt.options.generate.subFolders = true
const generator = new Generator(nuxt)
path.join.mockClear()
path.join.mockReturnValueOnce('/404/index.html')
const route = '/404'
const returned = await generator.generateRoute({ route })
expect(path.join).toBeCalledTimes(2)
expect(path.join).nthCalledWith(1, route, '[sep]', 'index.html')
expect(path.join).nthCalledWith(2, generator.distPath, '/404.html')
expect(fsExtra.writeFile).toBeCalledTimes(1)
expect(fsExtra.writeFile).toBeCalledWith(`join(${generator.distPath}, /404.html)`, 'rendered html', 'utf8')
expect(fsExtra.writeFile).toBeCalledWith(expect.any(String), 'rendered html', 'utf8')
expect(fsExtra.writeFile.mock.calls[0][0]).toBePath(
'/var/nuxt/generate/404.html',
'C:\\nuxt\\generate\\404.html'
)
expect(returned).toEqual(true)
})
@ -229,17 +229,17 @@ describe('generator: generate route', () => {
const nuxt = createNuxt()
nuxt.options.build.html = { minify: false }
const generator = new Generator(nuxt)
path.join.mockClear()
const route = ''
const returned = await generator.generateRoute({ route })
expect(path.join).toBeCalledTimes(2)
expect(path.join).nthCalledWith(1, '[sep]', 'index.html')
expect(path.join).nthCalledWith(2, generator.distPath, 'join([sep], index.html)')
expect(fsExtra.writeFile).toBeCalledTimes(1)
expect(fsExtra.writeFile).toBeCalledWith(`join(${generator.distPath}, join([sep], index.html))`, 'rendered html', 'utf8')
expect(fsExtra.writeFile).toBeCalledWith(expect.any(String), 'rendered html', 'utf8')
expect(fsExtra.writeFile.mock.calls[0][0]).toBePath(
'/var/nuxt/generate/index.html',
'C:\\nuxt\\generate\\index.html'
)
expect(returned).toEqual(true)
})
})

View File

@ -1,6 +1,4 @@
export default {
build: true,
rollup: {
externals: ['jsdom']
}
externals: ['jsdom']
}

View File

@ -8,11 +8,9 @@
"dist"
],
"dependencies": {
"@nuxt/config": "2.14.12",
"@nuxt/utils": "2.14.12",
"@nuxt/vue-renderer": "2.14.12",
"@nuxtjs/youch": "^4.2.3",
"chalk": "^4.1.0",
"compression": "^1.7.4",
"connect": "^3.7.0",
"consola": "^2.15.0",

View File

@ -4,8 +4,9 @@ import launchMiddleware from 'launch-editor-middleware'
import serveStatic from 'serve-static'
import servePlaceholder from 'serve-placeholder'
import connect from 'connect'
import compression from 'compression'
import { determineGlobals, isUrl, urlJoin } from '@nuxt/utils'
import { VueRenderer } from '@nuxt/vue-renderer'
import ServerContext from './context'
import renderAndGetWindow from './jsdom'
import nuxtMiddleware from './middleware/nuxt'
@ -53,8 +54,6 @@ export default class Server {
await this.nuxt.callHook('render:before', this, this.options.render)
// Initialize vue-renderer
const { VueRenderer } = await import('@nuxt/vue-renderer')
this.serverContext = new ServerContext(this)
this.renderer = new VueRenderer(this.serverContext)
await this.renderer.ready()
@ -77,7 +76,6 @@ export default class Server {
const { compressor } = this.options.render
if (typeof compressor === 'object') {
// If only setting for `compression` are provided, require the module and insert
const compression = this.nuxt.resolver.requireModule('compression')
this.useMiddleware(compression(compressor))
} else if (compressor) {
// Else, require own compression middleware if compressor is actually truthy

View File

@ -1,4 +1,5 @@
import path from 'path'
import compression from 'compression'
import connect from 'connect'
import consola from 'consola'
import serveStatic from 'serve-static'
@ -15,6 +16,7 @@ import nuxtMiddleware from '../src/middleware/nuxt'
import errorMiddleware from '../src/middleware/error'
import createTimingMiddleware from '../src/middleware/timing'
jest.mock('compression')
jest.mock('connect')
jest.mock('serve-static')
jest.mock('serve-placeholder')
@ -229,12 +231,11 @@ describe('server: server', () => {
server.useMiddleware.mockClear()
nuxt.options.render.compressor = { id: 'test-render-compressor' }
nuxt.resolver.requireModule.mockImplementationOnce(name => jest.fn(options => ({
name,
compression.mockImplementationOnce(options => ({
name: 'compression',
...options
})))
}))
await server.setupMiddleware()
expect(nuxt.resolver.requireModule).nthCalledWith(1, 'compression')
expect(server.useMiddleware).nthCalledWith(1, {
id: 'test-render-compressor',
name: 'compression'

View File

@ -10,8 +10,10 @@
"dependencies": {
"@nuxt/ufo": "^0.5.2",
"consola": "^2.15.0",
"create-require": "^1.1.1",
"fs-extra": "^9.0.1",
"hash-sum": "^2.0.0",
"lodash": "^4.17.20",
"proper-lockfile": "^4.1.1",
"semver": "^7.3.4",
"serialize-javascript": "^5.0.1",

View File

@ -1,4 +1,7 @@
import { join } from 'path'
import createRequire from 'create-require'
const _require = createRequire()
export function isHMRCompatible (id) {
return !/[/\\]mongoose[/\\/]/.test(id)
@ -16,7 +19,7 @@ export function clearRequireCache (id) {
const entry = getRequireCacheItem(id)
if (!entry) {
delete require.cache[id]
delete _require.cache[id]
return
}
@ -25,7 +28,7 @@ export function clearRequireCache (id) {
}
// Needs to be cleared before children, to protect against circular deps (#7966)
delete require.cache[id]
delete _require.cache[id]
for (const child of entry.children) {
clearRequireCache(child.id)
@ -55,18 +58,34 @@ export function scanRequireTree (id, files = new Set()) {
export function getRequireCacheItem (id) {
try {
return require.cache[id]
return _require.cache[id]
} catch (e) {
}
}
export function tryRequire (id) {
try {
return require(id)
} catch (e) {
export function resolveModule (id, paths) {
if (typeof paths === 'string') {
paths = [paths]
}
return _require.resolve(id, [
process.cwd(),
...(paths || []),
...(global.__NUXT_PATHS__ || [])
])
}
export function getPKG (id) {
return tryRequire(join(id, 'package.json'))
export function requireModule (id, paths) {
return _require(resolveModule(id, paths))
}
export function tryRequire (id, paths) {
try { return requireModule(id, paths) } catch (e) { }
}
export function tryResolve (id, paths) {
try { return resolveModule(id, paths) } catch (e) { }
}
export function getPKG (id, paths) {
return tryRequire(join(id, 'package.json'), paths)
}

View File

@ -1,4 +1,5 @@
import UAParser from 'ua-parser-js'
import semver from 'semver'
export const ModernBrowsers = {
Edge: '16',
@ -14,7 +15,6 @@ export const ModernBrowsers = {
'Mobile Safari': '10.3'
}
let semver
let __modernBrowsers
const getModernBrowsers = () => {
@ -34,9 +34,6 @@ export const isModernBrowser = (ua) => {
if (!ua) {
return false
}
if (!semver) {
semver = require('semver')
}
const { browser } = UAParser(ua)
const browserVersion = semver.coerce(browser.version)
if (!browserVersion) {

View File

@ -1,6 +1,6 @@
import path from 'path'
import consola from 'consola'
import escapeRegExp from 'lodash/escapeRegExp'
import { escapeRegExp } from 'lodash'
export const startsWithAlias = aliasArray => str => aliasArray.some(c => str.startsWith(c))
@ -105,5 +105,5 @@ export function isIndexFileAndFolder (pluginFiles) {
}
export const getMainModule = () => {
return require.main || (module && module.main) || module
return (require && require.main) || (module && module.main) || module
}

View File

@ -1,5 +1,5 @@
import path from 'path'
import get from 'lodash/get'
import { get } from 'lodash'
import consola from 'consola'
import { normalizeURL, withTrailingSlash, withoutTrailingSlash } from '@nuxt/ufo'
import { r } from './resolve'

View File

@ -1,3 +1,16 @@
export default {
build: true
build: true,
ignoreUnused: [
// used in vue-app
'@nuxt/ufo',
'node-fetch',
'unfetch',
'vue',
'vue-client-only',
'vue-meta',
'vue-no-ssr',
'vue-router',
'vue-template-compiler',
'vuex'
]
}

View File

@ -13,6 +13,7 @@
"@nuxt/utils": "2.14.12",
"consola": "^2.15.0",
"fs-extra": "^9.0.1",
"lodash": "^4.17.20",
"lru-cache": "^5.1.1",
"vue": "^2.6.12",
"vue-meta": "^2.4.0",

View File

@ -1,7 +1,7 @@
import path from 'path'
import fs from 'fs-extra'
import consola from 'consola'
import template from 'lodash/template'
import { template } from 'lodash'
import { TARGETS, isModernRequest, waitFor } from '@nuxt/utils'
import { normalizeURL } from '@nuxt/ufo'

View File

@ -1,5 +1,5 @@
import { extname } from 'path'
import cloneDeep from 'lodash/cloneDeep'
import { cloneDeep } from 'lodash'
import VueMeta from 'vue-meta'
import { createRenderer } from 'vue-server-renderer'
import LRU from 'lru-cache'

View File

@ -1,3 +1,18 @@
export default {
build: true
build: true,
ignoreUnused: [
'@nuxt/babel-preset-app',
'babel-loader',
'cache-loader',
'caniuse-lite',
'css-loader',
'cssnano',
'eventsource-polyfill',
'file-loader',
'postcss-loader',
'postcss-preset-env',
'postcss-url',
'style-resources-loader',
'url-loader'
]
}

View File

@ -8,16 +8,13 @@
"dist"
],
"dependencies": {
"@babel/core": "^7.12.10",
"@nuxt/babel-preset-app": "2.14.12",
"@nuxt/friendly-errors-webpack-plugin": "^2.5.0",
"@nuxt/utils": "2.14.12",
"babel-loader": "^8.2.2",
"cache-loader": "^4.1.0",
"caniuse-lite": "^1.0.30001170",
"chalk": "^4.1.0",
"caniuse-lite": "^1.0.30001168",
"consola": "^2.15.0",
"create-require": "^1.1.1",
"css-loader": "^4.3.0",
"cssnano": "^4.1.10",
"eventsource-polyfill": "^0.9.6",
@ -27,9 +24,11 @@
"hard-source-webpack-plugin": "^0.13.1",
"hash-sum": "^2.0.0",
"html-webpack-plugin": "^4.5.0",
"lodash": "^4.17.20",
"memory-fs": "^0.5.0",
"optimize-css-assets-webpack-plugin": "^5.0.4",
"pify": "^5.0.0",
"pnp-webpack-plugin": "^1.6.4",
"postcss": "^7.0.32",
"postcss-import": "^12.0.1",
"postcss-import-resolver": "^2.0.0",

View File

@ -6,7 +6,7 @@ import webpackDevMiddleware from 'webpack-dev-middleware'
import webpackHotMiddleware from 'webpack-hot-middleware'
import consola from 'consola'
import { TARGETS, parallel, sequence, wrapArray, isModernRequest } from '@nuxt/utils'
import { TARGETS, parallel, sequence, tryResolve, wrapArray, isModernRequest } from '@nuxt/utils'
import AsyncMFS from './utils/async-mfs'
import * as WebpackConfigs from './config'
@ -92,7 +92,7 @@ export class WebpackBundler {
// Warm up perfLoader before build
if (options.build.parallel) {
consola.info('Warming up worker pools')
PerfLoader.warmupAll({ dev: options.dev })
PerfLoader.warmupAll({ dev: options.dev, resolveModule: id => tryResolve(id, __filename) || id })
consola.success('Worker pools ready')
}

View File

@ -1,19 +1,18 @@
import path from 'path'
import consola from 'consola'
import TimeFixPlugin from 'time-fix-plugin'
import cloneDeep from 'lodash/cloneDeep'
import escapeRegExp from 'lodash/escapeRegExp'
import { escapeRegExp, cloneDeep } from 'lodash'
import VueLoader from 'vue-loader'
import ExtractCssChunksPlugin from 'extract-css-chunks-webpack-plugin'
import * as PnpWebpackPlugin from 'pnp-webpack-plugin'
import HardSourcePlugin from 'hard-source-webpack-plugin'
import TerserWebpackPlugin from 'terser-webpack-plugin'
import WebpackBar from 'webpackbar'
import env from 'std-env'
import semver from 'semver'
import { TARGETS, isUrl, urlJoin, getPKG } from '@nuxt/utils'
import { TARGETS, isUrl, urlJoin, getPKG, tryResolve, requireModule } from '@nuxt/utils'
import createRequire from 'create-require'
import PerfLoader from '../utils/perf-loader'
import StyleLoader from '../utils/style-loader'
import WarningIgnorePlugin from '../plugins/warning-ignore'
@ -23,6 +22,7 @@ export default class WebpackBaseConfig {
constructor (builder) {
this.builder = builder
this.buildContext = builder.buildContext
this.resolveModule = id => tryResolve(id) || id
}
get colors () {
@ -121,7 +121,7 @@ export default class WebpackBaseConfig {
let corejsVersion = corejs
if (corejsVersion === 'auto') {
try {
corejsVersion = Number.parseInt(createRequire(rootDir)('core-js/package.json').version.split('.')[0])
corejsVersion = Number.parseInt(requireModule('core-js/package.json', rootDir).version.split('.')[0])
} catch (_err) {
corejsVersion = 2
}
@ -134,7 +134,7 @@ export default class WebpackBaseConfig {
corejsVersion = 2
}
const defaultPreset = [require.resolve('@nuxt/babel-preset-app'), {
const defaultPreset = [this.resolveModule('@nuxt/babel-preset-app'), {
corejs: {
version: corejsVersion
}
@ -229,12 +229,20 @@ export default class WebpackBaseConfig {
resolve: {
extensions: ['.wasm', '.mjs', '.js', '.json', '.vue', '.jsx'],
alias: this.alias(),
modules: webpackModulesDir
modules: webpackModulesDir,
plugins: [
PnpWebpackPlugin,
PnpWebpackPlugin.moduleLoader(this.buildContext.options.rootDir),
PnpWebpackPlugin.moduleLoader(__dirname)
]
},
resolveLoader: {
modules: [
path.resolve(__dirname, '../node_modules'),
...webpackModulesDir
],
plugins: [
PnpWebpackPlugin.moduleLoader(module)
]
}
}
@ -271,26 +279,26 @@ export default class WebpackBaseConfig {
alias () {
return {
...this.buildContext.options.alias,
'vue-meta': require.resolve(`vue-meta${this.isServer ? '' : '/dist/vue-meta.esm.browser.js'}`)
'vue-meta': this.resolveModule(`vue-meta${this.isServer ? '' : '/dist/vue-meta.esm.browser.js'}`)
}
}
rules () {
const perfLoader = new PerfLoader(this.name, this.buildContext)
const perfLoader = new PerfLoader(this.name, this.buildContext, { resolveModule: this.resolveModule })
const styleLoader = new StyleLoader(
this.buildContext,
{ isServer: this.isServer, perfLoader }
{ isServer: this.isServer, perfLoader, resolveModule: this.resolveModule }
)
const babelLoader = {
loader: require.resolve('babel-loader'),
loader: this.resolveModule('babel-loader'),
options: this.getBabelOptions()
}
return [
{
test: /\.vue$/i,
loader: 'vue-loader',
loader: this.resolveModule('vue-loader'),
options: this.loaders.vue
},
{
@ -299,15 +307,15 @@ export default class WebpackBaseConfig {
{
resourceQuery: /^\?vue/i,
use: [{
loader: 'pug-plain-loader',
loader: this.resolveModule('pug-plain-loader'),
options: this.loaders.pugPlain
}]
},
{
use: [
'raw-loader',
this.resolveModule('raw-loader'),
{
loader: 'pug-plain-loader',
loader: this.resolveModule('pug-plain-loader'),
options: this.loaders.pugPlain
}
]
@ -340,35 +348,35 @@ export default class WebpackBaseConfig {
{
test: /\.less$/i,
oneOf: styleLoader.apply('less', {
loader: 'less-loader',
loader: this.resolveModule('less-loader'),
options: this.loaders.less
})
},
{
test: /\.sass$/i,
oneOf: styleLoader.apply('sass', {
loader: 'sass-loader',
loader: this.resolveModule('sass-loader'),
options: this.loaders.sass
})
},
{
test: /\.scss$/i,
oneOf: styleLoader.apply('scss', {
loader: 'sass-loader',
loader: this.resolveModule('sass-loader'),
options: this.loaders.scss
})
},
{
test: /\.styl(us)?$/i,
oneOf: styleLoader.apply('stylus', {
loader: 'stylus-loader',
loader: this.resolveModule('stylus-loader'),
options: this.loaders.stylus
})
},
{
test: /\.(png|jpe?g|gif|svg|webp|avif)$/i,
use: [{
loader: 'url-loader',
loader: this.resolveModule('url-loader'),
options: Object.assign(
this.loaders.imgUrl,
{ name: this.getFileName('img') }
@ -378,7 +386,7 @@ export default class WebpackBaseConfig {
{
test: /\.(woff2?|eot|ttf|otf)(\?.*)?$/i,
use: [{
loader: 'url-loader',
loader: this.resolveModule('url-loader'),
options: Object.assign(
this.loaders.fontUrl,
{ name: this.getFileName('font') }
@ -388,7 +396,7 @@ export default class WebpackBaseConfig {
{
test: /\.(webm|mp4|ogv)$/i,
use: [{
loader: 'file-loader',
loader: this.resolveModule('file-loader'),
options: Object.assign(
this.loaders.file,
{ name: this.getFileName('video') }

View File

@ -199,9 +199,9 @@ export default class WebpackClientConfig extends WebpackBaseConfig {
if (this.dev) {
config.entry.app.unshift(
// https://github.com/webpack-contrib/webpack-hot-middleware/issues/53#issuecomment-162823945
'eventsource-polyfill',
this.resolveModule('eventsource-polyfill'),
// https://github.com/glenjamin/webpack-hot-middleware#config
`webpack-hot-middleware/client?${hotMiddlewareClientOptionsStr}`
`${this.resolveModule('webpack-hot-middleware/client')}?${hotMiddlewareClientOptionsStr}`
)
}

View File

@ -4,7 +4,7 @@
*/
import hash from 'hash-sum'
import uniq from 'lodash/uniq'
import { uniq } from 'lodash'
import { isJS, isCSS } from './util'

View File

@ -6,10 +6,11 @@ import { warmup } from 'thread-loader'
// https://github.com/webpack-contrib/cache-loader
export default class PerfLoader {
constructor (name, buildContext) {
constructor (name, buildContext, { resolveModule }) {
this.name = name
this.buildContext = buildContext
this.workerPools = PerfLoader.defaultPools({ dev: buildContext.options.dev })
this.resolveModule = resolveModule
return new Proxy(this, {
get (target, name) {
return target[name] ? target[name] : target.use.bind(target, name)
@ -25,13 +26,13 @@ export default class PerfLoader {
}
}
static warmupAll ({ dev }) {
static warmupAll ({ dev, resolveModule }) {
const pools = PerfLoader.defaultPools({ dev })
PerfLoader.warmup(pools.js, [
require.resolve('babel-loader'),
require.resolve('@babel/preset-env')
resolveModule('babel-loader'),
resolveModule('@babel/preset-env')
])
PerfLoader.warmup(pools.css, ['css-loader'])
PerfLoader.warmup(pools.css, [resolveModule('css-loader')])
}
static warmup (...args) {
@ -43,7 +44,7 @@ export default class PerfLoader {
if (this.buildContext.buildOptions.cache) {
loaders.push({
loader: 'cache-loader',
loader: this.resolveModule('cache-loader'),
options: {
cacheDirectory: path.resolve(`node_modules/.cache/cache-loader/${this.name}`)
}
@ -54,7 +55,7 @@ export default class PerfLoader {
const pool = this.workerPools[poolName]
if (pool) {
loaders.push({
loader: 'thread-loader',
loader: this.resolveModule('thread-loader'),
options: pool
})
}

View File

@ -1,9 +1,7 @@
import fs from 'fs'
import path from 'path'
import consola from 'consola'
import defaults from 'lodash/defaults'
import merge from 'lodash/merge'
import cloneDeep from 'lodash/cloneDeep'
import { defaults, merge, cloneDeep } from 'lodash'
import createResolver from 'postcss-import-resolver'
import { isPureObject } from '@nuxt/utils'

View File

@ -6,10 +6,11 @@ import { wrapArray } from '@nuxt/utils'
import PostcssConfig from './postcss'
export default class StyleLoader {
constructor (buildContext, { isServer, perfLoader }) {
constructor (buildContext, { isServer, perfLoader, resolveModule }) {
this.buildContext = buildContext
this.isServer = isServer
this.perfLoader = perfLoader
this.resolveModule = resolveModule
if (buildContext.options.build.postcss) {
this.postcssConfig = new PostcssConfig(buildContext)
@ -40,7 +41,7 @@ export default class StyleLoader {
const patterns = wrapArray(extResource).map(p => path.resolve(rootDir, p))
return {
loader: 'style-resources-loader',
loader: this.resolveModule('style-resources-loader'),
options: Object.assign(
{ patterns },
styleResources.options || {}
@ -62,13 +63,13 @@ export default class StyleLoader {
}
return {
loader: 'postcss-loader',
loader: this.resolveModule('postcss-loader'),
options: Object.assign({ sourceMap: this.buildContext.buildOptions.cssSourceMap }, config)
}
}
css (options) {
const cssLoader = { loader: 'css-loader', options }
const cssLoader = { loader: this.resolveModule('css-loader'), options }
if (this.exportOnlyLocals) {
options.modules = {
@ -102,7 +103,7 @@ export default class StyleLoader {
styleLoader () {
return this.extract() || {
loader: 'vue-style-loader',
loader: this.resolveModule('vue-style-loader'),
options: this.buildContext.buildOptions.loaders.vueStyle
}
}

View File

@ -1,8 +1,6 @@
import consola from 'consola'
import execa from 'execa'
import groupBy from 'lodash/groupBy'
import sortBy from 'lodash/sortBy'
import uniq from 'lodash/uniq'
import { uniq, sortBy, groupBy } from 'lodash'
import { writeFile } from 'fs-extra'
const types = {

View File

@ -1,4 +1,3 @@
#!/usr/bin/env node -r esm
import path from 'path'
import fs from 'fs-extra'
import consola from 'consola'
@ -11,7 +10,7 @@ const useCjs = [
const stub = {
es: 'export * from \'../src/index\'',
cjs: `const _require = typeof jest === 'undefined' ? require('esm')(module) : require
cjs: `const _require = typeof jest === 'undefined' ? require('jiti')(__dirname) : require
global.__NUXT_DEV__ = true
module.exports = _require('../src/index')
`

View File

@ -1,8 +1,11 @@
const path = require('path')
const consola = require('consola')
const execa = require('execa')
const fs = require('fs-extra')
const glob = require('pify')(require('glob'))
import path from 'path'
import consola from 'consola'
import execa from 'execa'
import fs from 'fs-extra'
import _glob from 'glob'
import pify from 'pify'
const glob = pify(_glob) // TODO: use globby
async function main () {
const packageDirs = await glob('+(packages|distributions)/*')

View File

@ -1,5 +1,3 @@
#!/usr/bin/env node -r esm
import consola from 'consola'
import Package from './package.js'

View File

@ -9,6 +9,7 @@ import pify from 'pify'
import sortPackageJson from 'sort-package-json'
import rollupConfig from './rollup.config'
import { builtins } from './builtins'
const DEFAULTS = {
rootDir: process.cwd(),
@ -185,11 +186,22 @@ export default class Package {
}
async build (_watch = false) {
// Externals
const externals = [
// Dependencies that will be installed alongise with the nuxt package
...Object.keys(this.pkg.dependencies || {}),
// Builtin node modules
...builtins,
// Custom externals
...(this.options.externals || [])
]
// Prepare rollup config
const config = {
rootDir: this.options.rootDir,
alias: {},
replace: {},
externals,
...this.options.rollup
}
@ -250,27 +262,30 @@ export default class Package {
try {
const bundle = await rollup(_rollupConfig)
await remove(_rollupConfig.output.dir)
await bundle.write(_rollupConfig.output)
const result = await bundle.write(_rollupConfig.output)
this.logger.success('Bundle built')
await this.callHook('build:done', { bundle })
// Analyze bundle imports against pkg
// if (this.pkg.dependencies) {
// const dependencies = {}
// for (const dep in this.pkg.dependencies) {
// dependencies[dep] = this.pkg.dependencies[dep]
// }
// for (const imp of bundle.imports) {
// delete dependencies[imp]
// }
// for (const dep in dependencies) {
// this.logger.warn(`Unused dependency ${dep}@${dependencies[dep]}`)
// }
// }
const dependencies = Object.keys(this.pkg.dependencies || {})
const imports = [].concat(...result.output.map(o => o.imports))
const missingDependencies = imports
.filter(i => !i.endsWith('.js')) // dynamic imports
.filter(i => !dependencies.includes(i) && !externals.find(e => i.startsWith(e)))
if (missingDependencies.length) {
throw new Error(`Missing dependencies in ${this.pkg.name}: ` + missingDependencies.join(', '))
}
const ignoreUnused = this.options.ignoreUnused || []
const unusedDependencies = dependencies.filter(d =>
!imports.find(i => i.startsWith(d)) && !ignoreUnused.includes(d)
)
if (unusedDependencies.length) {
throw new Error(`Unused dependencies in ${this.pkg.name}: ` + unusedDependencies.join(', '))
}
} catch (err) {
this.formatError(err)
this.logger.error(err)
throw err
}
}
@ -282,7 +297,7 @@ export default class Package {
const { file, column, line } = error.loc
loc = `${file}:${line}:${column}`
}
error.message = `[${error.code}] ${error.message}\nat ${loc}`
error.message = `[${error.code || ''}] ${error.message}\nat ${loc}`
return error
}

View File

@ -4,11 +4,9 @@ import jsonPlugin from '@rollup/plugin-json'
import commonjsPlugin from '@rollup/plugin-commonjs'
import replacePlugin from '@rollup/plugin-replace'
import aliasPlugin from '@rollup/plugin-alias'
import nodeResolvePlugin from '@rollup/plugin-node-resolve'
// import nodeResolvePlugin from '@rollup/plugin-node-resolve'
import licensePlugin from 'rollup-plugin-license'
import defaultsDeep from 'lodash/defaultsDeep'
import { builtins } from './builtins'
import { defaultsDeep } from 'lodash'
export default function rollupConfig ({
rootDir = process.cwd(),
@ -17,12 +15,6 @@ export default function rollupConfig ({
replace = {},
alias = {},
externals = [],
resolve = {
resolveOnly: [
/lodash/,
/^((?!node_modules).)*$/
]
},
...options
}, pkg) {
if (!pkg) {
@ -40,14 +32,7 @@ export default function rollupConfig ({
format: 'cjs',
preferConst: true
},
external: [
// Dependencies that will be installed alongise with the nuxt package
...Object.keys(pkg.dependencies || {}),
// Builtin node modules
...builtins,
// Explicit externals
...externals
],
external: externals,
plugins: [
aliasPlugin(alias),
replacePlugin({
@ -58,7 +43,12 @@ export default function rollupConfig ({
...replace
}
}),
nodeResolvePlugin(resolve),
// nodeResolvePlugin({
// preferBuiltins: true,
// resolveOnly: [
// /lodash/
// ]
// }),
commonjsPlugin({ include: /node_modules/ }),
jsonPlugin(),
licensePlugin({

View File

@ -6,12 +6,13 @@ describe('webpack configuration', () => {
test('performance loader', () => {
const js = { name: 'js', poolTimeout: Infinity }
const css = { name: 'css', poolTimeout: Infinity }
const resolveModule = jest.fn(id => id)
PerfLoader.warmup = jest.fn()
PerfLoader.warmupAll({ dev: true })
PerfLoader.warmupAll({ dev: true, resolveModule })
expect(PerfLoader.warmup).toHaveBeenCalledTimes(2)
expect(PerfLoader.warmup).toHaveBeenCalledWith(js, [
require.resolve('babel-loader'),
require.resolve('@babel/preset-env')
'babel-loader',
'@babel/preset-env'
])
expect(PerfLoader.warmup).toHaveBeenCalledWith(css, ['css-loader'])
@ -25,6 +26,9 @@ describe('webpack configuration', () => {
parallel: true,
cache: true
}
},
{
resolveModule
}
)
expect(perfLoader.workerPools).toMatchObject({ js, css })

View File

@ -1,5 +1,5 @@
import { resolve } from 'path'
import defaultsDeep from 'lodash/defaultsDeep'
import { defaultsDeep } from 'lodash'
import baseNuxtConfig from '../spa/nuxt.config'
const config = {

View File

@ -1,5 +1,5 @@
import { resolve } from 'path'
import defaultsDeep from 'lodash/defaultsDeep'
import { defaultsDeep } from 'lodash'
import baseNuxtConfig from '../spa/nuxt.config'
const config = {

View File

@ -8,7 +8,7 @@ import path from 'path'
import { execSync, execFileSync } from 'child_process'
import isWsl from 'is-wsl'
import consola from 'consola'
import uniq from 'lodash/uniq'
import { uniq } from 'lodash'
const newLineRegex = /\r?\n/

View File

@ -21,3 +21,15 @@ function errorTrap (error) {
process.on('unhandledRejection', errorTrap)
process.on('uncaughtException', errorTrap)
expect.extend({
toBePath (received, posixPath, winPath) {
const expectedPath = isWin ? winPath : posixPath
const pass = received === expectedPath
return {
pass,
message: () =>
`expected path ${received} to be ${expectedPath}`
}
}
})

View File

@ -3966,7 +3966,7 @@ caniuse-lite@^1.0.0, caniuse-lite@^1.0.30000981, caniuse-lite@^1.0.30001109, can
resolved "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001168.tgz#6fcd098c139d003b9bd484cbb9ca26cb89907f9a"
integrity sha512-P2zmX7swIXKu+GMMR01TWa4csIKELTNnZKc+f1CjebmZJQtTAEXmpQSoKVJVVcvPGAA0TEYTOUp3VehavZSFPQ==
caniuse-lite@^1.0.30001170:
caniuse-lite@^1.0.30001168:
version "1.0.30001170"
resolved "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001170.tgz#0088bfecc6a14694969e391cc29d7eb6362ca6a7"
integrity sha512-Dd4d/+0tsK0UNLrZs3CvNukqalnVTRrxb5mcQm8rHL49t7V5ZaTygwXkrq+FB+dVDf++4ri8eJnFEJAB8332PA==
@ -4973,7 +4973,7 @@ debug@3.1.0:
dependencies:
ms "2.0.0"
debug@4, debug@^4.0.1, debug@^4.1.0, debug@^4.1.1, debug@^4.2.0:
debug@4, debug@^4.0.1, debug@^4.1.0, debug@^4.1.1:
version "4.3.1"
resolved "https://registry.npmjs.org/debug/-/debug-4.3.1.tgz#f0d229c505e0c6d8c49ac553d1b13dc183f6b2ee"
integrity sha512-doEwdvm4PCeK4K3RQN2ZC2BYUBaxwLARCqZmMjtF8a51J2Rb0xpVloFRnCODwqjpwnAoao4pelN8l3RJdv3gRQ==
@ -5761,11 +5761,6 @@ eslint@^7.16.0:
text-table "^0.2.0"
v8-compile-cache "^2.0.3"
esm@^3.2.25:
version "3.2.25"
resolved "https://registry.npmjs.org/esm/-/esm-3.2.25.tgz#342c18c29d56157688ba5ce31f8431fbb795cc10"
integrity sha512-U1suiZ2oDVWv4zPO56S0NcR5QriEahGtdN2OR6FiOG4WJvcjBVFB0qI4+eKoWFH483PKGuLuu6V8Z4T5g63UVA==
espree@^6.2.1:
version "6.2.1"
resolved "https://registry.npmjs.org/espree/-/espree-6.2.1.tgz#77fc72e1fd744a2052c20f38a5b575832e82734a"
@ -8500,7 +8495,7 @@ lodash@4.17.19:
resolved "https://registry.npmjs.org/lodash/-/lodash-4.17.19.tgz#e48ddedbe30b3321783c5b4301fbd353bc1e4a4b"
integrity sha512-JNvd8XER9GQX0v2qJgsaN/mzFCNA5BRe/j8JN9d+tWyGLSodKQHKFicdwNYzWwI3wjRnaKPsGj1XkBjx/F96DQ==
lodash@^4.15.0, lodash@^4.17.12, lodash@^4.17.15, lodash@^4.17.19, lodash@^4.17.20, lodash@^4.17.5, lodash@^4.2.1:
lodash@^4.15.0, lodash@^4.17.12, lodash@^4.17.15, lodash@^4.17.19, lodash@^4.17.20, lodash@^4.17.5, lodash@^4.2.1, lodash@^4.4.2:
version "4.17.20"
resolved "https://registry.npmjs.org/lodash/-/lodash-4.17.20.tgz#b44a9b6297bcb698f1c51a3545a2b3b368d59c52"
integrity sha512-PlhdFcillOINfeV7Ni6oF1TAEayyZBoZ8bcshTHqOYJYlrqzRK5hagpagky5o4HfCzzd1TRkXPMFq6cKk9rGmA==
@ -10041,6 +10036,13 @@ pluralize@^8.0.0:
resolved "https://registry.npmjs.org/pluralize/-/pluralize-8.0.0.tgz#1a6fa16a38d12a1901e0320fa017051c539ce3b1"
integrity sha512-Nc3IT5yHzflTfbjgqWcCPpo7DaKy4FnpB0l/zCAW0Tc7jxAiuqSxHasntB3D7887LSrA93kDJ9IXovxJYxyLCA==
pnp-webpack-plugin@^1.6.4:
version "1.6.4"
resolved "https://registry.npmjs.org/pnp-webpack-plugin/-/pnp-webpack-plugin-1.6.4.tgz#c9711ac4dc48a685dabafc86f8b6dd9f8df84149"
integrity sha512-7Wjy+9E3WwLOEL30D+m8TSTF7qJJUJLONBnwQp0518siuMxUQUbgZwssaFX+QKlZkjHZcw/IpZCt/H0srrntSg==
dependencies:
ts-pnp "^1.1.6"
posix-character-classes@^0.1.0:
version "0.1.1"
resolved "https://registry.npmjs.org/posix-character-classes/-/posix-character-classes-0.1.1.tgz#01eac0fe3b5af71a2a6c02feabb8c1fef7e00eab"
@ -12768,6 +12770,11 @@ ts-jest@26.x:
semver "7.x"
yargs-parser "20.x"
ts-pnp@^1.1.6:
version "1.2.0"
resolved "https://registry.npmjs.org/ts-pnp/-/ts-pnp-1.2.0.tgz#a500ad084b0798f1c3071af391e65912c86bca92"
integrity sha512-csd+vJOb/gkzvcCHgTGSChYpy5f1/XKNsmvBGO4JXS+z1v2HobugDz4s1IeFXM3wZB44uczs+eazB5Q/ccdhQw==
tsconfig-paths@^3.9.0:
version "3.9.0"
resolved "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-3.9.0.tgz#098547a6c4448807e8fcb8eae081064ee9a3c90b"
@ -13052,11 +13059,6 @@ url-loader@^4.1.1:
mime-types "^2.1.27"
schema-utils "^3.0.0"
url-polyfill@^1.1.12:
version "1.1.12"
resolved "https://registry.npmjs.org/url-polyfill/-/url-polyfill-1.1.12.tgz#6cdaa17f6b022841b3aec0bf8dbd87ac0cd33331"
integrity sha512-mYFmBHCapZjtcNHW0MDq9967t+z4Dmg5CJ0KqysK3+ZbyoNOWQHksGCTWwDhxGXllkWlOc10Xfko6v4a3ucM6A==
url@^0.11.0:
version "0.11.0"
resolved "https://registry.npmjs.org/url/-/url-0.11.0.tgz#3838e97cfc60521eb73c525a8e55bfdd9e2e28f1"