Update loader-utils (#30743)
Co-authored-by: jj@jjsweb.site <jj@jjsweb.site> Co-authored-by: Steven <steven@ceriously.com> Co-authored-by: Jiachi Liu <inbox@huozhi.im>
This commit is contained in:
parent
d5d1bc0012
commit
cbc52d1b31
28 changed files with 236 additions and 202 deletions
|
@ -1,4 +1,3 @@
|
|||
import { getOptions } from 'next/dist/compiled/loader-utils'
|
||||
import { Span } from '../../../trace'
|
||||
import transform from './transform'
|
||||
import { NextJsLoaderContext } from './types'
|
||||
|
@ -13,7 +12,8 @@ async function nextBabelLoader(
|
|||
const target = this.target
|
||||
const loaderOptions = parentTrace
|
||||
.traceChild('get-options')
|
||||
.traceFn(() => getOptions(this))
|
||||
// @ts-ignore TODO: remove ignore once webpack 5 types are used
|
||||
.traceFn(() => this.getOptions())
|
||||
|
||||
const loaderSpanInner = parentTrace.traceChild('next-babel-turbo-transform')
|
||||
const { code: transformedSource, map: outputSourceMap } =
|
||||
|
|
|
@ -2,7 +2,6 @@
|
|||
MIT License http://www.opensource.org/licenses/mit-license.php
|
||||
Author Tobias Koppers @sokra
|
||||
*/
|
||||
import { getOptions, stringifyRequest } from 'next/dist/compiled/loader-utils'
|
||||
import postcss from 'postcss'
|
||||
|
||||
import CssSyntaxError from './CssSyntaxError'
|
||||
|
@ -23,9 +22,10 @@ import {
|
|||
normalizeSourceMap,
|
||||
sort,
|
||||
} from './utils'
|
||||
import { stringifyRequest } from '../../../stringify-request'
|
||||
|
||||
export default async function loader(content, map, meta) {
|
||||
const rawOptions = getOptions(this)
|
||||
const rawOptions = this.getOptions()
|
||||
|
||||
const plugins = []
|
||||
const callback = this.async()
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
import chalk from 'chalk'
|
||||
import loaderUtils from 'next/dist/compiled/loader-utils'
|
||||
import path from 'path'
|
||||
import { webpack } from 'next/dist/compiled/webpack/webpack'
|
||||
|
||||
const ErrorLoader: webpack.loader.Loader = function () {
|
||||
const options = loaderUtils.getOptions(this) || {}
|
||||
// @ts-ignore exists
|
||||
const options = this.getOptions() || {}
|
||||
|
||||
const { reason = 'An unknown error has occurred' } = options
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import loaderUtils from 'next/dist/compiled/loader-utils'
|
||||
import { stringifyRequest } from '../stringify-request'
|
||||
|
||||
export type ClientPagesLoaderOptions = {
|
||||
absolutePagePath: string
|
||||
|
@ -12,16 +12,12 @@ function nextClientPagesLoader(this: any) {
|
|||
)
|
||||
|
||||
return pagesLoaderSpan.traceFn(() => {
|
||||
const { absolutePagePath, page } = loaderUtils.getOptions(
|
||||
this
|
||||
) as ClientPagesLoaderOptions
|
||||
const { absolutePagePath, page } =
|
||||
this.getOptions() as ClientPagesLoaderOptions
|
||||
|
||||
pagesLoaderSpan.setAttribute('absolutePagePath', absolutePagePath)
|
||||
|
||||
const stringifiedPagePath = loaderUtils.stringifyRequest(
|
||||
this,
|
||||
absolutePagePath
|
||||
)
|
||||
const stringifiedPagePath = stringifyRequest(this, absolutePagePath)
|
||||
const stringifiedPage = JSON.stringify(page)
|
||||
|
||||
return `
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
import loaderUtils from 'next/dist/compiled/loader-utils'
|
||||
import * as acorn from 'acorn'
|
||||
import { getRawPageExtensions } from '../../utils'
|
||||
|
||||
|
@ -81,7 +80,7 @@ export default async function transformSource(
|
|||
source: string
|
||||
): Promise<string> {
|
||||
const { client: isClientCompilation, pageExtensions: pageExtensionsJson } =
|
||||
loaderUtils.getOptions(this)
|
||||
this.getOptions()
|
||||
const { resourcePath } = this
|
||||
const pageExtensions = JSON.parse(pageExtensionsJson)
|
||||
|
||||
|
|
|
@ -8,8 +8,7 @@ const VALID_BLUR_EXT = ['jpeg', 'png', 'webp', 'avif'] // should match next/clie
|
|||
function nextImageLoader(content) {
|
||||
const imageLoaderSpan = this.currentTraceSpan.traceChild('next-image-loader')
|
||||
return imageLoaderSpan.traceAsyncFn(async () => {
|
||||
const { isServer, isDev, assetPrefix, basePath } =
|
||||
loaderUtils.getOptions(this)
|
||||
const { isServer, isDev, assetPrefix, basePath } = this.getOptions()
|
||||
const context = this.rootContext
|
||||
const opts = { context, content }
|
||||
const interpolatedName = loaderUtils.interpolateName(
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import loaderUtils from 'next/dist/compiled/loader-utils'
|
||||
import { stringifyRequest } from '../stringify-request'
|
||||
|
||||
export type MiddlewareLoaderOptions = {
|
||||
absolutePagePath: string
|
||||
|
@ -6,12 +6,8 @@ export type MiddlewareLoaderOptions = {
|
|||
}
|
||||
|
||||
export default function middlewareLoader(this: any) {
|
||||
const { absolutePagePath, page }: MiddlewareLoaderOptions =
|
||||
loaderUtils.getOptions(this)
|
||||
const stringifiedPagePath = loaderUtils.stringifyRequest(
|
||||
this,
|
||||
absolutePagePath
|
||||
)
|
||||
const { absolutePagePath, page }: MiddlewareLoaderOptions = this.getOptions()
|
||||
const stringifiedPagePath = stringifyRequest(this, absolutePagePath)
|
||||
|
||||
return `
|
||||
import { adapter } from 'next/dist/server/web/adapter'
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
import loaderUtils from 'next/dist/compiled/loader-utils'
|
||||
import { getStringifiedAbsolutePath } from './utils'
|
||||
import { stringifyRequest } from '../../stringify-request'
|
||||
|
||||
const fallbackDocumentPage = `
|
||||
import { Html, Head, Main, NextScript } from 'next/document'
|
||||
|
@ -31,14 +31,13 @@ export default async function middlewareRSCLoader(this: any) {
|
|||
const {
|
||||
absolutePagePath,
|
||||
basePath,
|
||||
isServerComponent,
|
||||
isServerComponent: isServerComponentQuery,
|
||||
assetPrefix,
|
||||
buildId,
|
||||
} = loaderUtils.getOptions(this)
|
||||
const stringifiedAbsolutePagePath = loaderUtils.stringifyRequest(
|
||||
this,
|
||||
absolutePagePath
|
||||
)
|
||||
} = this.getOptions()
|
||||
|
||||
const isServerComponent = isServerComponentQuery === 'true'
|
||||
const stringifiedAbsolutePagePath = stringifyRequest(this, absolutePagePath)
|
||||
const stringifiedAbsoluteDocumentPath = getStringifiedAbsolutePath(
|
||||
this,
|
||||
'./pages/_document'
|
||||
|
@ -48,9 +47,11 @@ export default async function middlewareRSCLoader(this: any) {
|
|||
'./pages/_app'
|
||||
)
|
||||
|
||||
const hasProvidedAppPage = hasModule(JSON.parse(stringifiedAbsoluteAppPath))
|
||||
const hasProvidedAppPage = hasModule(
|
||||
this.utils.absolutify(this.rootContext, './pages/_app')
|
||||
)
|
||||
const hasProvidedDocumentPage = hasModule(
|
||||
JSON.parse(stringifiedAbsoluteDocumentPath)
|
||||
this.utils.absolutify(this.rootContext, './pages/_document')
|
||||
)
|
||||
|
||||
let appDefinition = `const App = require(${
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
import loaderUtils from 'next/dist/compiled/loader-utils'
|
||||
import { stringifyRequest } from '../../stringify-request'
|
||||
|
||||
export function getStringifiedAbsolutePath(target: any, path: string) {
|
||||
return loaderUtils.stringifyRequest(
|
||||
return stringifyRequest(
|
||||
target,
|
||||
target.utils.absolutify(target.rootContext, path)
|
||||
)
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
import devalue from 'next/dist/compiled/devalue'
|
||||
import escapeRegexp from 'next/dist/compiled/escape-string-regexp'
|
||||
import loaderUtils from 'next/dist/compiled/loader-utils'
|
||||
import { join } from 'path'
|
||||
import { parse } from 'querystring'
|
||||
import { webpack } from 'next/dist/compiled/webpack/webpack'
|
||||
|
@ -12,6 +11,7 @@ import {
|
|||
ROUTES_MANIFEST,
|
||||
REACT_LOADABLE_MANIFEST,
|
||||
} from '../../../../shared/lib/constants'
|
||||
import { stringifyRequest } from '../../stringify-request'
|
||||
|
||||
export type ServerlessLoaderQuery = {
|
||||
page: string
|
||||
|
@ -113,10 +113,7 @@ const nextServerlessLoader: webpack.loader.Loader = function () {
|
|||
}
|
||||
|
||||
const apiHandler = getApiHandler({
|
||||
pageModule: require(${loaderUtils.stringifyRequest(
|
||||
this,
|
||||
absolutePagePath
|
||||
)}),
|
||||
pageModule: require(${stringifyRequest(this, absolutePagePath)}),
|
||||
rewrites: combinedRewrites,
|
||||
i18n: ${i18n || 'undefined'},
|
||||
page: "${page}",
|
||||
|
@ -141,21 +138,15 @@ const nextServerlessLoader: webpack.loader.Loader = function () {
|
|||
}
|
||||
import { getPageHandler } from 'next/dist/build/webpack/loaders/next-serverless-loader/page-handler'
|
||||
|
||||
const documentModule = require(${loaderUtils.stringifyRequest(
|
||||
const documentModule = require(${stringifyRequest(
|
||||
this,
|
||||
absoluteDocumentPath
|
||||
)})
|
||||
|
||||
const appMod = require(${loaderUtils.stringifyRequest(
|
||||
this,
|
||||
absoluteAppPath
|
||||
)})
|
||||
const appMod = require(${stringifyRequest(this, absoluteAppPath)})
|
||||
let App = appMod.default || appMod.then && appMod.then(mod => mod.default);
|
||||
|
||||
const compMod = require(${loaderUtils.stringifyRequest(
|
||||
this,
|
||||
absolutePagePath
|
||||
)})
|
||||
const compMod = require(${stringifyRequest(this, absolutePagePath)})
|
||||
|
||||
const Component = compMod.default || compMod.then && compMod.then(mod => mod.default)
|
||||
export default Component
|
||||
|
@ -188,13 +179,10 @@ const nextServerlessLoader: webpack.loader.Loader = function () {
|
|||
pageConfig: config,
|
||||
appModule: App,
|
||||
documentModule: documentModule,
|
||||
errorModule: require(${loaderUtils.stringifyRequest(
|
||||
this,
|
||||
absoluteErrorPath
|
||||
)}),
|
||||
errorModule: require(${stringifyRequest(this, absoluteErrorPath)}),
|
||||
notFoundModule: ${
|
||||
absolute404Path
|
||||
? `require(${loaderUtils.stringifyRequest(this, absolute404Path)})`
|
||||
? `require(${stringifyRequest(this, absolute404Path)})`
|
||||
: undefined
|
||||
},
|
||||
pageGetStaticProps: getStaticProps,
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
import loaderUtils from 'next/dist/compiled/loader-utils'
|
||||
import path from 'path'
|
||||
import isEqualLocals from './runtime/isEqualLocals'
|
||||
import { stringifyRequest } from '../../stringify-request'
|
||||
|
||||
const loaderApi = () => {}
|
||||
|
||||
|
@ -8,7 +8,7 @@ loaderApi.pitch = function loader(request) {
|
|||
const loaderSpan = this.currentTraceSpan.traceChild('next-style-loader')
|
||||
|
||||
return loaderSpan.traceFn(() => {
|
||||
const options = loaderUtils.getOptions(this)
|
||||
const options = this.getOptions()
|
||||
|
||||
const insert =
|
||||
typeof options.insert === 'undefined'
|
||||
|
@ -28,15 +28,12 @@ loaderApi.pitch = function loader(request) {
|
|||
? `
|
||||
if (module.hot) {
|
||||
module.hot.accept(
|
||||
${loaderUtils.stringifyRequest(this, `!!${request}`)},
|
||||
${stringifyRequest(this, `!!${request}`)},
|
||||
function() {
|
||||
${
|
||||
esModule
|
||||
? 'update(content);'
|
||||
: `content = require(${loaderUtils.stringifyRequest(
|
||||
this,
|
||||
`!!${request}`
|
||||
)});
|
||||
: `content = require(${stringifyRequest(this, `!!${request}`)});
|
||||
|
||||
content = content.__esModule ? content.default : content;
|
||||
|
||||
|
@ -53,22 +50,16 @@ if (module.hot) {
|
|||
|
||||
return `${
|
||||
esModule
|
||||
? `import api from ${loaderUtils.stringifyRequest(
|
||||
? `import api from ${stringifyRequest(
|
||||
this,
|
||||
`!${path.join(__dirname, 'runtime/injectStylesIntoLinkTag.js')}`
|
||||
)};
|
||||
import content from ${loaderUtils.stringifyRequest(
|
||||
this,
|
||||
`!!${request}`
|
||||
)};`
|
||||
: `var api = require(${loaderUtils.stringifyRequest(
|
||||
import content from ${stringifyRequest(this, `!!${request}`)};`
|
||||
: `var api = require(${stringifyRequest(
|
||||
this,
|
||||
`!${path.join(__dirname, 'runtime/injectStylesIntoLinkTag.js')}`
|
||||
)});
|
||||
var content = require(${loaderUtils.stringifyRequest(
|
||||
this,
|
||||
`!!${request}`
|
||||
)});
|
||||
var content = require(${stringifyRequest(this, `!!${request}`)});
|
||||
|
||||
content = content.__esModule ? content.default : content;`
|
||||
}
|
||||
|
@ -96,7 +87,7 @@ if (module.hot) {
|
|||
var oldLocals = content.locals;
|
||||
|
||||
module.hot.accept(
|
||||
${loaderUtils.stringifyRequest(this, `!!${request}`)},
|
||||
${stringifyRequest(this, `!!${request}`)},
|
||||
function () {
|
||||
${
|
||||
esModule
|
||||
|
@ -111,10 +102,7 @@ if (module.hot) {
|
|||
if (update && refs > 0) {
|
||||
update(content);
|
||||
}`
|
||||
: `content = require(${loaderUtils.stringifyRequest(
|
||||
this,
|
||||
`!!${request}`
|
||||
)});
|
||||
: `content = require(${stringifyRequest(this, `!!${request}`)});
|
||||
|
||||
content = content.__esModule ? content.default : content;
|
||||
|
||||
|
@ -144,28 +132,22 @@ if (module.hot) {
|
|||
|
||||
return `${
|
||||
esModule
|
||||
? `import api from ${loaderUtils.stringifyRequest(
|
||||
? `import api from ${stringifyRequest(
|
||||
this,
|
||||
`!${path.join(
|
||||
__dirname,
|
||||
'runtime/injectStylesIntoStyleTag.js'
|
||||
)}`
|
||||
)};
|
||||
import content from ${loaderUtils.stringifyRequest(
|
||||
this,
|
||||
`!!${request}`
|
||||
)};`
|
||||
: `var api = require(${loaderUtils.stringifyRequest(
|
||||
import content from ${stringifyRequest(this, `!!${request}`)};`
|
||||
: `var api = require(${stringifyRequest(
|
||||
this,
|
||||
`!${path.join(
|
||||
__dirname,
|
||||
'runtime/injectStylesIntoStyleTag.js'
|
||||
)}`
|
||||
)});
|
||||
var content = require(${loaderUtils.stringifyRequest(
|
||||
this,
|
||||
`!!${request}`
|
||||
)});
|
||||
var content = require(${stringifyRequest(this, `!!${request}`)});
|
||||
|
||||
content = content.__esModule ? content.default : content;
|
||||
|
||||
|
@ -216,7 +198,7 @@ if (module.hot) {
|
|||
var oldLocals = content.locals;
|
||||
|
||||
module.hot.accept(
|
||||
${loaderUtils.stringifyRequest(this, `!!${request}`)},
|
||||
${stringifyRequest(this, `!!${request}`)},
|
||||
function () {
|
||||
${
|
||||
esModule
|
||||
|
@ -229,10 +211,7 @@ if (module.hot) {
|
|||
oldLocals = content.locals;
|
||||
|
||||
update(content);`
|
||||
: `content = require(${loaderUtils.stringifyRequest(
|
||||
this,
|
||||
`!!${request}`
|
||||
)});
|
||||
: `content = require(${stringifyRequest(this, `!!${request}`)});
|
||||
|
||||
content = content.__esModule ? content.default : content;
|
||||
|
||||
|
@ -262,28 +241,22 @@ if (module.hot) {
|
|||
|
||||
return `${
|
||||
esModule
|
||||
? `import api from ${loaderUtils.stringifyRequest(
|
||||
? `import api from ${stringifyRequest(
|
||||
this,
|
||||
`!${path.join(
|
||||
__dirname,
|
||||
'runtime/injectStylesIntoStyleTag.js'
|
||||
)}`
|
||||
)};
|
||||
import content from ${loaderUtils.stringifyRequest(
|
||||
this,
|
||||
`!!${request}`
|
||||
)};`
|
||||
: `var api = require(${loaderUtils.stringifyRequest(
|
||||
import content from ${stringifyRequest(this, `!!${request}`)};`
|
||||
: `var api = require(${stringifyRequest(
|
||||
this,
|
||||
`!${path.join(
|
||||
__dirname,
|
||||
'runtime/injectStylesIntoStyleTag.js'
|
||||
)}`
|
||||
)});
|
||||
var content = require(${loaderUtils.stringifyRequest(
|
||||
this,
|
||||
`!!${request}`
|
||||
)});
|
||||
var content = require(${stringifyRequest(this, `!!${request}`)});
|
||||
|
||||
content = content.__esModule ? content.default : content;
|
||||
|
||||
|
|
|
@ -26,7 +26,6 @@ IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
|||
DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
import { getOptions } from 'next/dist/compiled/loader-utils'
|
||||
import { transform } from '../../swc'
|
||||
|
||||
const nextDistPath =
|
||||
|
@ -117,7 +116,7 @@ async function loaderTransform(parentTrace, source, inputSourceMap) {
|
|||
// Make the loader async
|
||||
const filename = this.resourcePath
|
||||
|
||||
let loaderOptions = getOptions(this) || {}
|
||||
let loaderOptions = this.getOptions() || {}
|
||||
|
||||
const { isServer, pagesDir, hasReactRefresh } = loaderOptions
|
||||
const isPageFile = filename.startsWith(pagesDir)
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
import Warning from './Warning'
|
||||
import SyntaxError from './Error'
|
||||
import { normalizeSourceMap, normalizeSourceMapAfterPostcss } from './utils'
|
||||
import { getOptions } from 'next/dist/compiled/loader-utils'
|
||||
|
||||
/**
|
||||
* **PostCSS Loader**
|
||||
|
@ -22,7 +21,7 @@ export default async function loader(content, sourceMap, meta) {
|
|||
|
||||
loaderSpan
|
||||
.traceAsyncFn(async () => {
|
||||
const options = getOptions(this)
|
||||
const options = this.getOptions()
|
||||
const file = this.resourcePath
|
||||
|
||||
const useSourceMap =
|
||||
|
|
8
packages/next/build/webpack/stringify-request.ts
Normal file
8
packages/next/build/webpack/stringify-request.ts
Normal file
|
@ -0,0 +1,8 @@
|
|||
export function stringifyRequest(loaderContext: any, request: any) {
|
||||
return JSON.stringify(
|
||||
loaderContext.utils.contextify(
|
||||
loaderContext.context || loaderContext.rootContext,
|
||||
request
|
||||
)
|
||||
)
|
||||
}
|
8
packages/next/bundles/loader-utils.js
Normal file
8
packages/next/bundles/loader-utils.js
Normal file
|
@ -0,0 +1,8 @@
|
|||
/* eslint-disable import/no-extraneous-dependencies */
|
||||
const loaderUtils = require('loader-utils')
|
||||
|
||||
loaderUtils.getOptions = function (context) {
|
||||
return context.getOptions()
|
||||
}
|
||||
|
||||
module.exports = loaderUtils
|
File diff suppressed because one or more lines are too long
1
packages/next/compiled/loader-utils/loader-utils.js
Normal file
1
packages/next/compiled/loader-utils/loader-utils.js
Normal file
File diff suppressed because one or more lines are too long
|
@ -1 +1 @@
|
|||
{"name":"loader-utils","main":"index.js","author":"Tobias Koppers @sokra","license":"MIT"}
|
||||
{"name":"loader-utils","main":"loader-utils.js","author":"Tobias Koppers @sokra","license":"MIT"}
|
||||
|
|
|
@ -224,7 +224,7 @@
|
|||
"is-wsl": "2.2.0",
|
||||
"json5": "2.2.0",
|
||||
"jsonwebtoken": "8.5.1",
|
||||
"loader-utils": "2.0.0",
|
||||
"loader-utils": "3.1.0",
|
||||
"lodash.curry": "4.1.1",
|
||||
"lru-cache": "5.1.1",
|
||||
"micromatch": "4.0.4",
|
||||
|
|
|
@ -359,7 +359,7 @@ export async function ncc_jsonwebtoken(task, opts) {
|
|||
externals['loader-utils'] = 'next/dist/compiled/loader-utils'
|
||||
export async function ncc_loader_utils(task, opts) {
|
||||
await task
|
||||
.source(opts.src || relative(__dirname, require.resolve('loader-utils')))
|
||||
.source(opts.src || 'bundles/loader-utils.js')
|
||||
.ncc({ packageName: 'loader-utils', externals })
|
||||
.target('compiled/loader-utils')
|
||||
}
|
||||
|
|
|
@ -72,7 +72,7 @@ const runTests = (isDev = false) => {
|
|||
expect(html).toContain(
|
||||
`style="position:absolute;top:0;left:0;bottom:0;right:0;box-sizing:border-box;padding:0;border:none;margin:auto;display:block;width:0;height:0;min-width:100%;max-width:100%;min-height:100%;max-height:100%;filter:blur(20px);background-size:cover;background-image:url(${
|
||||
isDev
|
||||
? '"/docs/_next/image?url=%2Fdocs%2F_next%2Fstatic%2Fmedia%2Ftest.480a01e5.jpg&w=8&q=70"'
|
||||
? '"/docs/_next/image?url=%2Fdocs%2F_next%2Fstatic%2Fmedia%2Ftest.fab2915d.jpg&w=8&q=70"'
|
||||
: '"data:image/jpeg;base64,/9j/4AAQSkZJRgABAQAAAQABAAD/2wCEAAoKCgoKCgsMDAsPEA4QDxYUExMUFiIYGhgaGCIzICUgICUgMy03LCksNy1RQDg4QFFeT0pPXnFlZXGPiI+7u/sBCgoKCgoKCwwMCw8QDhAPFhQTExQWIhgaGBoYIjMgJSAgJSAzLTcsKSw3LVFAODhAUV5PSk9ecWVlcY+Ij7u7+//CABEIAAYACAMBIgACEQEDEQH/xAAnAAEBAAAAAAAAAAAAAAAAAAAABwEBAAAAAAAAAAAAAAAAAAAAAP/aAAwDAQACEAMQAAAAmgP/xAAcEAACAQUBAAAAAAAAAAAAAAASFBMAAQMFERX/2gAIAQEAAT8AZ1HjrKZX55JysIc4Ff/EABQRAQAAAAAAAAAAAAAAAAAAAAD/2gAIAQIBAT8Af//EABQRAQAAAAAAAAAAAAAAAAAAAAD/2gAIAQMBAT8Af//Z"'
|
||||
});background-position:0% 0%"`
|
||||
)
|
||||
|
@ -81,7 +81,7 @@ const runTests = (isDev = false) => {
|
|||
expect(html).toContain(
|
||||
`style="position:absolute;top:0;left:0;bottom:0;right:0;box-sizing:border-box;padding:0;border:none;margin:auto;display:block;width:0;height:0;min-width:100%;max-width:100%;min-height:100%;max-height:100%;filter:blur(20px);background-size:cover;background-image:url(${
|
||||
isDev
|
||||
? '"/docs/_next/image?url=%2Fdocs%2F_next%2Fstatic%2Fmedia%2Ftest.eba16dd4.png&w=8&q=70"'
|
||||
? '"/docs/_next/image?url=%2Fdocs%2F_next%2Fstatic%2Fmedia%2Ftest.3f1a293b.png&w=8&q=70"'
|
||||
: '"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAMAAAAICAAAAAAZhBqgAAAAJklEQVR42mNgkmBkYGXgZGBoY2Co/lPAcOf/dYaCzHwGEBAVEwUAZZIG0TbWicQAAAAASUVORK5CYII="'
|
||||
});background-position:0% 0%"`
|
||||
)
|
||||
|
|
|
@ -694,7 +694,7 @@ function runTests({
|
|||
if (!isDev) {
|
||||
const filename = 'test'
|
||||
const query = {
|
||||
url: `/_next/static/media/${filename}.480a01e5.jpg`,
|
||||
url: `/_next/static/media/${filename}.fab2915d.jpg`,
|
||||
w,
|
||||
q: 100,
|
||||
}
|
||||
|
|
|
@ -12,6 +12,7 @@ import {
|
|||
nextStart,
|
||||
findPort,
|
||||
killApp,
|
||||
fetchViaHTTP,
|
||||
} from 'next-test-utils'
|
||||
import webdriver from 'next-webdriver'
|
||||
import {
|
||||
|
@ -20,7 +21,6 @@ import {
|
|||
REACT_LOADABLE_MANIFEST,
|
||||
} from 'next/constants'
|
||||
import { recursiveReadDir } from 'next/dist/lib/recursive-readdir'
|
||||
import fetch from 'node-fetch'
|
||||
import { join, sep } from 'path'
|
||||
import dynamicImportTests from './dynamic'
|
||||
import processEnv from './process-env'
|
||||
|
@ -300,42 +300,50 @@ describe('Production Usage', () => {
|
|||
})
|
||||
|
||||
it('should allow etag header support', async () => {
|
||||
const url = `http://localhost:${appPort}/`
|
||||
const etag = (await fetch(url)).headers.get('ETag')
|
||||
const url = `http://localhost:${appPort}`
|
||||
const etag = (await fetchViaHTTP(url, '/')).headers.get('ETag')
|
||||
|
||||
const headers = { 'If-None-Match': etag }
|
||||
const res2 = await fetch(url, { headers })
|
||||
const res2 = await fetchViaHTTP(url, '/', undefined, { headers })
|
||||
expect(res2.status).toBe(304)
|
||||
})
|
||||
|
||||
it('should allow etag header support with getStaticProps', async () => {
|
||||
const url = `http://localhost:${appPort}/fully-static`
|
||||
const etag = (await fetch(url)).headers.get('ETag')
|
||||
const url = `http://localhost:${appPort}`
|
||||
const etag = (await fetchViaHTTP(url, '/fully-static')).headers.get(
|
||||
'ETag'
|
||||
)
|
||||
|
||||
const headers = { 'If-None-Match': etag }
|
||||
const res2 = await fetch(url, { headers })
|
||||
const res2 = await fetchViaHTTP(url, '/fully-static', undefined, {
|
||||
headers,
|
||||
})
|
||||
expect(res2.status).toBe(304)
|
||||
})
|
||||
|
||||
it('should allow etag header support with getServerSideProps', async () => {
|
||||
const url = `http://localhost:${appPort}/fully-dynamic`
|
||||
const etag = (await fetch(url)).headers.get('ETag')
|
||||
const url = `http://localhost:${appPort}`
|
||||
const etag = (await fetchViaHTTP(url, '/fully-dynamic')).headers.get(
|
||||
'ETag'
|
||||
)
|
||||
|
||||
const headers = { 'If-None-Match': etag }
|
||||
const res2 = await fetch(url, { headers })
|
||||
const res2 = await fetchViaHTTP(url, '/fully-dynamic', undefined, {
|
||||
headers,
|
||||
})
|
||||
expect(res2.status).toBe(304)
|
||||
})
|
||||
|
||||
it('should have X-Powered-By header support', async () => {
|
||||
const url = `http://localhost:${appPort}/`
|
||||
const header = (await fetch(url)).headers.get('X-Powered-By')
|
||||
const url = `http://localhost:${appPort}`
|
||||
const header = (await fetchViaHTTP(url, '/')).headers.get('X-Powered-By')
|
||||
|
||||
expect(header).toBe('Next.js')
|
||||
})
|
||||
|
||||
it('should render 404 for routes that do not exist', async () => {
|
||||
const url = `http://localhost:${appPort}/abcdefghijklmno`
|
||||
const res = await fetch(url)
|
||||
const url = `http://localhost:${appPort}`
|
||||
const res = await fetchViaHTTP(url, '/abcdefghijklmno')
|
||||
const text = await res.text()
|
||||
const $html = cheerio.load(text)
|
||||
expect($html('html').text()).toMatch(/404/)
|
||||
|
@ -349,43 +357,57 @@ describe('Production Usage', () => {
|
|||
})
|
||||
|
||||
it('should render 200 for POST on page', async () => {
|
||||
const res = await fetch(`http://localhost:${appPort}/about`, {
|
||||
method: 'POST',
|
||||
})
|
||||
const res = await fetchViaHTTP(
|
||||
`http://localhost:${appPort}`,
|
||||
'/about',
|
||||
undefined,
|
||||
{
|
||||
method: 'POST',
|
||||
}
|
||||
)
|
||||
expect(res.status).toBe(200)
|
||||
})
|
||||
|
||||
it('should render 404 for POST on missing page', async () => {
|
||||
const res = await fetch(`http://localhost:${appPort}/fake-page`, {
|
||||
method: 'POST',
|
||||
})
|
||||
const res = await fetchViaHTTP(
|
||||
`http://localhost:${appPort}`,
|
||||
'/fake-page',
|
||||
undefined,
|
||||
{
|
||||
method: 'POST',
|
||||
}
|
||||
)
|
||||
expect(res.status).toBe(404)
|
||||
})
|
||||
|
||||
it('should render 404 for _next routes that do not exist', async () => {
|
||||
const url = `http://localhost:${appPort}/_next/abcdef`
|
||||
const res = await fetch(url)
|
||||
const url = `http://localhost:${appPort}`
|
||||
const res = await fetchViaHTTP(url, '/_next/abcdef')
|
||||
expect(res.status).toBe(404)
|
||||
})
|
||||
|
||||
it('should render 404 even if the HTTP method is not GET or HEAD', async () => {
|
||||
const url = `http://localhost:${appPort}/_next/abcdef`
|
||||
const url = `http://localhost:${appPort}`
|
||||
const methods = ['POST', 'PUT', 'DELETE']
|
||||
for (const method of methods) {
|
||||
const res = await fetch(url, { method })
|
||||
const res = await fetchViaHTTP(url, '/_next/abcdef', undefined, {
|
||||
method,
|
||||
})
|
||||
expect(res.status).toBe(404)
|
||||
}
|
||||
})
|
||||
|
||||
it('should render 404 for dotfiles in /static', async () => {
|
||||
const url = `http://localhost:${appPort}/static/.env`
|
||||
const res = await fetch(url)
|
||||
const url = `http://localhost:${appPort}`
|
||||
const res = await fetchViaHTTP(url, '/static/.env')
|
||||
expect(res.status).toBe(404)
|
||||
})
|
||||
|
||||
it('should return 405 method on static then GET and HEAD', async () => {
|
||||
const res = await fetch(
|
||||
`http://localhost:${appPort}/static/data/item.txt`,
|
||||
const res = await fetchViaHTTP(
|
||||
`http://localhost:${appPort}`,
|
||||
'/static/data/item.txt',
|
||||
undefined,
|
||||
{
|
||||
method: 'POST',
|
||||
}
|
||||
|
@ -403,10 +425,15 @@ describe('Production Usage', () => {
|
|||
const files = buildManifest.pages['/']
|
||||
|
||||
for (const file of files) {
|
||||
const res = await fetch(`http://localhost:${appPort}/_next/${file}`, {
|
||||
method: 'GET',
|
||||
headers: { 'if-unmodified-since': 'Fri, 12 Jul 2019 20:00:13 GMT' },
|
||||
})
|
||||
const res = await fetchViaHTTP(
|
||||
`http://localhost:${appPort}`,
|
||||
`/_next/${file}`,
|
||||
undefined,
|
||||
{
|
||||
method: 'GET',
|
||||
headers: { 'if-unmodified-since': 'Fri, 12 Jul 2019 20:00:13 GMT' },
|
||||
}
|
||||
)
|
||||
expect(res.status).toBe(412)
|
||||
}
|
||||
})
|
||||
|
@ -420,17 +447,22 @@ describe('Production Usage', () => {
|
|||
const files = buildManifest.pages['/']
|
||||
|
||||
for (const file of files) {
|
||||
const res = await fetch(`http://localhost:${appPort}/_next/${file}`, {
|
||||
method: 'GET',
|
||||
headers: { 'if-unmodified-since': 'nextjs' },
|
||||
})
|
||||
const res = await fetchViaHTTP(
|
||||
`http://localhost:${appPort}`,
|
||||
`/_next/${file}`,
|
||||
undefined,
|
||||
{
|
||||
method: 'GET',
|
||||
headers: { 'if-unmodified-since': 'nextjs' },
|
||||
}
|
||||
)
|
||||
expect(res.status).toBe(200)
|
||||
}
|
||||
})
|
||||
|
||||
it('should set Content-Length header', async () => {
|
||||
const url = `http://localhost:${appPort}`
|
||||
const res = await fetch(url)
|
||||
const res = await fetchViaHTTP(url, '/')
|
||||
expect(res.headers.get('Content-Length')).toBeDefined()
|
||||
})
|
||||
|
||||
|
@ -440,7 +472,7 @@ describe('Production Usage', () => {
|
|||
'../.next',
|
||||
REACT_LOADABLE_MANIFEST
|
||||
))
|
||||
const url = `http://localhost:${appPort}/_next/`
|
||||
const url = `http://localhost:${appPort}`
|
||||
|
||||
const resources = new Set()
|
||||
|
||||
|
@ -452,12 +484,12 @@ describe('Production Usage', () => {
|
|||
|
||||
// test dynamic chunk
|
||||
reactLoadableManifest[manifestKey].files.forEach((f) => {
|
||||
resources.add(url + f)
|
||||
resources.add('/' + f)
|
||||
})
|
||||
|
||||
// test main.js runtime etc
|
||||
for (const item of buildManifest.pages['/']) {
|
||||
resources.add(url + item)
|
||||
resources.add('/' + item)
|
||||
}
|
||||
|
||||
const cssStaticAssets = await recursiveReadDir(
|
||||
|
@ -473,11 +505,13 @@ describe('Production Usage', () => {
|
|||
expect(mediaStaticAssets.length).toBeGreaterThanOrEqual(1)
|
||||
expect(mediaStaticAssets[0]).toMatch(/[\\/]media[\\/]/)
|
||||
;[...cssStaticAssets, ...mediaStaticAssets].forEach((asset) => {
|
||||
resources.add(`${url}static${asset.replace(/\\+/g, '/')}`)
|
||||
resources.add(`/static${asset.replace(/\\+/g, '/')}`)
|
||||
})
|
||||
|
||||
const responses = await Promise.all(
|
||||
[...resources].map((resource) => fetch(resource))
|
||||
[...resources].map((resource) =>
|
||||
fetchViaHTTP(url, join('/_next', resource))
|
||||
)
|
||||
)
|
||||
|
||||
responses.forEach((res) => {
|
||||
|
@ -494,8 +528,9 @@ describe('Production Usage', () => {
|
|||
|
||||
it('should set correct Cache-Control header for static 404s', async () => {
|
||||
// this is to fix where 404 headers are set to 'public, max-age=31536000, immutable'
|
||||
const res = await fetch(
|
||||
`http://localhost:${appPort}/_next//static/common/bad-static.js`
|
||||
const res = await fetchViaHTTP(
|
||||
`http://localhost:${appPort}`,
|
||||
`/_next//static/common/bad-static.js`
|
||||
)
|
||||
|
||||
expect(res.status).toBe(404)
|
||||
|
@ -523,22 +558,22 @@ describe('Production Usage', () => {
|
|||
|
||||
describe('API routes', () => {
|
||||
it('should work with pages/api/index.js', async () => {
|
||||
const url = `http://localhost:${appPort}/api`
|
||||
const res = await fetch(url)
|
||||
const url = `http://localhost:${appPort}`
|
||||
const res = await fetchViaHTTP(url, `/api`)
|
||||
const body = await res.text()
|
||||
expect(body).toEqual('API index works')
|
||||
})
|
||||
|
||||
it('should work with pages/api/hello.js', async () => {
|
||||
const url = `http://localhost:${appPort}/api/hello`
|
||||
const res = await fetch(url)
|
||||
const url = `http://localhost:${appPort}`
|
||||
const res = await fetchViaHTTP(url, `/api/hello`)
|
||||
const body = await res.text()
|
||||
expect(body).toEqual('API hello works')
|
||||
})
|
||||
|
||||
it('should work with dynamic params and search string', async () => {
|
||||
const url = `http://localhost:${appPort}/api/post-1?val=1`
|
||||
const res = await fetch(url)
|
||||
const url = `http://localhost:${appPort}`
|
||||
const res = await fetchViaHTTP(url, `/api/post-1?val=1`)
|
||||
const body = await res.json()
|
||||
|
||||
expect(body).toEqual({ val: '1', post: 'post-1' })
|
||||
|
@ -901,16 +936,18 @@ describe('Production Usage', () => {
|
|||
|
||||
it('should not expose the compiled page file in development', async () => {
|
||||
const url = `http://localhost:${appPort}`
|
||||
await fetch(`${url}/stateless`) // make sure the stateless page is built
|
||||
const clientSideJsRes = await fetch(
|
||||
`${url}/_next/development/static/development/pages/stateless.js`
|
||||
await fetchViaHTTP(`${url}`, `/stateless`) // make sure the stateless page is built
|
||||
const clientSideJsRes = await fetchViaHTTP(
|
||||
`${url}`,
|
||||
'/_next/development/static/development/pages/stateless.js'
|
||||
)
|
||||
expect(clientSideJsRes.status).toBe(404)
|
||||
const clientSideJsBody = await clientSideJsRes.text()
|
||||
expect(clientSideJsBody).toMatch(/404/)
|
||||
|
||||
const serverSideJsRes = await fetch(
|
||||
`${url}/_next/development/server/static/development/pages/stateless.js`
|
||||
const serverSideJsRes = await fetchViaHTTP(
|
||||
`${url}`,
|
||||
'/_next/development/server/static/development/pages/stateless.js'
|
||||
)
|
||||
expect(serverSideJsRes.status).toBe(404)
|
||||
const serverSideJsBody = await serverSideJsRes.text()
|
||||
|
|
4
test/integration/react-18/app/node_modules/react-dom/package.json
generated
vendored
4
test/integration/react-18/app/node_modules/react-dom/package.json
generated
vendored
|
@ -1,4 +0,0 @@
|
|||
{
|
||||
"name": "react-dom",
|
||||
"version": "18.0.0-alpha-c76e4dbbc-20210722"
|
||||
}
|
|
@ -10,6 +10,7 @@ import {
|
|||
import { writeFile } from 'fs-extra'
|
||||
import getPort from 'get-port'
|
||||
import http from 'http'
|
||||
import https from 'https'
|
||||
import server from 'next/dist/server/next'
|
||||
import _pkg from 'next/package.json'
|
||||
import fetch from 'node-fetch'
|
||||
|
@ -102,7 +103,19 @@ export function fetchViaHTTP(appPort, pathname, query, opts) {
|
|||
const url = `${pathname}${
|
||||
typeof query === 'string' ? query : query ? `?${qs.stringify(query)}` : ''
|
||||
}`
|
||||
return fetch(getFullUrl(appPort, url), opts)
|
||||
return fetch(getFullUrl(appPort, url), {
|
||||
// in node.js v17 fetch favors IPv6 but Next.js is
|
||||
// listening on IPv4 by default so force IPv4 DNS resolving
|
||||
agent: (parsedUrl) => {
|
||||
if (parsedUrl.protocol === 'https:') {
|
||||
return new https.Agent({ family: 4 })
|
||||
}
|
||||
if (parsedUrl.protocol === 'http:') {
|
||||
return new http.Agent({ family: 4 })
|
||||
}
|
||||
},
|
||||
...opts,
|
||||
})
|
||||
}
|
||||
|
||||
export function findPort() {
|
||||
|
|
|
@ -10,6 +10,18 @@ const babel = async (code: string, queryOpts = {} as any) => {
|
|||
const { isServer = false, resourcePath = `index.js` } = queryOpts
|
||||
|
||||
let isAsync = false
|
||||
|
||||
const options = {
|
||||
// loader opts
|
||||
cwd: dir,
|
||||
isServer,
|
||||
distDir: path.resolve(dir, '.next'),
|
||||
pagesDir:
|
||||
'pagesDir' in queryOpts ? queryOpts.pagesDir : path.resolve(dir, 'pages'),
|
||||
cache: false,
|
||||
development: true,
|
||||
hasReactRefresh: !isServer,
|
||||
}
|
||||
return new Promise<string>((resolve, reject) => {
|
||||
function callback(err, content) {
|
||||
if (err) {
|
||||
|
@ -27,18 +39,10 @@ const babel = async (code: string, queryOpts = {} as any) => {
|
|||
},
|
||||
callback,
|
||||
emitWarning() {},
|
||||
query: {
|
||||
// loader opts
|
||||
cwd: dir,
|
||||
isServer,
|
||||
distDir: path.resolve(dir, '.next'),
|
||||
pagesDir:
|
||||
'pagesDir' in queryOpts
|
||||
? queryOpts.pagesDir
|
||||
: path.resolve(dir, 'pages'),
|
||||
cache: false,
|
||||
development: true,
|
||||
hasReactRefresh: !isServer,
|
||||
query: options,
|
||||
// @ts-ignore exists
|
||||
getOptions: function () {
|
||||
return options
|
||||
},
|
||||
currentTraceSpan: new Span({ name: 'test' }),
|
||||
})(code, null)
|
||||
|
|
|
@ -19,6 +19,19 @@ const babel = async (code: string, queryOpts = {} as any) => {
|
|||
}
|
||||
}
|
||||
|
||||
const options = {
|
||||
// loader opts
|
||||
cwd: dir,
|
||||
isServer,
|
||||
distDir: path.resolve(dir, '.next'),
|
||||
pagesDir:
|
||||
'pagesDir' in queryOpts
|
||||
? queryOpts.pagesDir
|
||||
: path.resolve(dir, 'pages'),
|
||||
cache: false,
|
||||
hasReactRefresh: false,
|
||||
}
|
||||
|
||||
const res = loader.bind({
|
||||
resourcePath,
|
||||
async() {
|
||||
|
@ -27,17 +40,10 @@ const babel = async (code: string, queryOpts = {} as any) => {
|
|||
},
|
||||
callback,
|
||||
emitWarning() {},
|
||||
query: {
|
||||
// loader opts
|
||||
cwd: dir,
|
||||
isServer,
|
||||
distDir: path.resolve(dir, '.next'),
|
||||
pagesDir:
|
||||
'pagesDir' in queryOpts
|
||||
? queryOpts.pagesDir
|
||||
: path.resolve(dir, 'pages'),
|
||||
cache: false,
|
||||
hasReactRefresh: false,
|
||||
query: options,
|
||||
// @ts-ignore exists
|
||||
getOptions: function () {
|
||||
return options
|
||||
},
|
||||
currentTraceSpan: new Span({ name: 'test' }),
|
||||
})(code, null)
|
||||
|
|
24
yarn.lock
24
yarn.lock
|
@ -6319,6 +6319,11 @@ big.js@^5.2.2:
|
|||
version "5.2.2"
|
||||
resolved "https://registry.yarnpkg.com/big.js/-/big.js-5.2.2.tgz#65f0af382f578bcdc742bd9c281e9cb2d7768328"
|
||||
|
||||
big.js@^6.1.1:
|
||||
version "6.1.1"
|
||||
resolved "https://registry.yarnpkg.com/big.js/-/big.js-6.1.1.tgz#63b35b19dc9775c94991ee5db7694880655d5537"
|
||||
integrity sha512-1vObw81a8ylZO5ePrtMay0n018TcftpTA5HFKDaSuiUDBo8biRBtjIobw60OpwuvrGk+FsxKamqN4cnmj/eXdg==
|
||||
|
||||
binary-extensions@^1.0.0:
|
||||
version "1.13.1"
|
||||
resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-1.13.1.tgz#598afe54755b2868a5330d2aff9d4ebb53209b65"
|
||||
|
@ -12729,13 +12734,12 @@ loader-utils@1.2.3:
|
|||
emojis-list "^2.0.0"
|
||||
json5 "^1.0.1"
|
||||
|
||||
loader-utils@2.0.0, loader-utils@^2.0.0:
|
||||
version "2.0.0"
|
||||
resolved "https://registry.yarnpkg.com/loader-utils/-/loader-utils-2.0.0.tgz#e4cace5b816d425a166b5f097e10cd12b36064b0"
|
||||
loader-utils@3.1.0:
|
||||
version "3.1.0"
|
||||
resolved "https://registry.yarnpkg.com/loader-utils/-/loader-utils-3.1.0.tgz#5d6583148713e4c022b3dac9daac0efd9b6bca42"
|
||||
integrity sha512-7YF6k8Q9xXFHkQhVaX76PyJVAIcPAKNk+7zJs5w2k/wVqkb8uq8O6MIWuY50BkuinY2WD5Ugmpu0oVipDexFkQ==
|
||||
dependencies:
|
||||
big.js "^5.2.2"
|
||||
emojis-list "^3.0.0"
|
||||
json5 "^2.1.2"
|
||||
big.js "^6.1.1"
|
||||
|
||||
loader-utils@^1.1.0, loader-utils@^1.2.3:
|
||||
version "1.4.0"
|
||||
|
@ -12745,6 +12749,14 @@ loader-utils@^1.1.0, loader-utils@^1.2.3:
|
|||
emojis-list "^3.0.0"
|
||||
json5 "^1.0.1"
|
||||
|
||||
loader-utils@^2.0.0:
|
||||
version "2.0.0"
|
||||
resolved "https://registry.yarnpkg.com/loader-utils/-/loader-utils-2.0.0.tgz#e4cace5b816d425a166b5f097e10cd12b36064b0"
|
||||
dependencies:
|
||||
big.js "^5.2.2"
|
||||
emojis-list "^3.0.0"
|
||||
json5 "^2.1.2"
|
||||
|
||||
locate-path@^2.0.0:
|
||||
version "2.0.0"
|
||||
resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-2.0.0.tgz#2b568b265eec944c6d9c0de9c3dbbbca0354cd8e"
|
||||
|
|
Loading…
Reference in a new issue