Add profiling to webpack loaders (#20392)

Follow-up to #20357 with additional tracers.
This commit is contained in:
Tim Neutkens 2020-12-29 22:21:35 +01:00 committed by GitHub
parent 52270af307
commit 5c5108fe0d
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
18 changed files with 588 additions and 288 deletions

3
.vscode/launch.json vendored
View file

@ -22,7 +22,8 @@
"runtimeExecutable": "yarn",
"runtimeArgs": ["run", "debug", "build", "test/integration/basic"],
"skipFiles": ["<node_internals>/**"],
"port": 9229
"port": 9229,
"outFiles": ["${workspaceFolder}/packages/next/dist/**/*"]
},
{
"name": "Launch app production",

View file

@ -4,5 +4,6 @@
"javascriptreact",
{ "language": "typescript", "autoFix": true },
{ "language": "typescriptreact", "autoFix": true }
]
],
"debug.javascript.unmapMissingSources": true
}

View file

@ -0,0 +1,35 @@
const STRIP_FILENAME_RE = /^[^:]+: /
const format = (err) => {
if (err instanceof SyntaxError) {
err.name = 'SyntaxError'
err.message = err.message.replace(STRIP_FILENAME_RE, '')
err.hideStack = true
} else if (err instanceof TypeError) {
err.name = null
err.message = err.message.replace(STRIP_FILENAME_RE, '')
err.hideStack = true
}
return err
}
class LoaderError extends Error {
constructor(err) {
super()
const { name, message, codeFrame, hideStack } = format(err)
this.name = 'BabelLoaderError'
this.message = `${name ? `${name}: ` : ''}${message}\n\n${codeFrame}\n`
this.hideStack = hideStack
Error.captureStackTrace(this, this.constructor)
}
}
export default LoaderError

View file

@ -0,0 +1,57 @@
import { createHash } from 'crypto'
import { tracer, traceAsyncFn } from '../../../../tracer'
import transform from './transform'
import cacache from 'next/dist/compiled/cacache'
async function read(cacheDirectory, etag) {
const cachedResult = await traceAsyncFn(
tracer.startSpan('read-cache-file'),
async () => await cacache.get(cacheDirectory, etag)
)
return JSON.parse(cachedResult.data)
}
function write(cacheDirectory, etag, data) {
return cacache.put(cacheDirectory, etag, JSON.stringify(data))
}
const etag = function (source, identifier, options) {
const hash = createHash('md4')
const contents = JSON.stringify({ source, options, identifier })
hash.update(contents)
return hash.digest('hex')
}
export default async function handleCache(params) {
const span = tracer.startSpan('handle-cache')
return traceAsyncFn(span, async () => {
const { source, options = {}, cacheIdentifier, cacheDirectory } = params
const file = etag(source, cacheIdentifier)
try {
// No errors mean that the file was previously cached
// we just need to return it
const res = await read(cacheDirectory, file)
span.setAttribute('cache', res ? 'HIT' : 'MISS')
return res
} catch (err) {}
// Otherwise just transform the file
// return it to the user asap and write it in cache
const result = await traceAsyncFn(
tracer.startSpan('transform'),
async () => {
return transform(source, options)
}
)
await write(cacheDirectory, file, result)
return result
})
}

View file

@ -0,0 +1,168 @@
// import babel from 'next/dist/compiled/babel/core'
import loaderUtils from 'loader-utils'
import { tracer, traceAsyncFn, traceFn } from '../../../../tracer'
import cache from './cache'
import transform from './transform'
// When using `import` Babel will be undefined
const babel = require('next/dist/compiled/babel/core')
export default function makeLoader(callback) {
const overrides = callback(babel)
return function (source, inputSourceMap) {
// Make the loader async
const cb = this.async()
loader.call(this, source, inputSourceMap, overrides).then(
(args) => cb(null, ...args),
(err) => cb(err)
)
}
}
async function loader(source, inputSourceMap, overrides) {
const span = tracer.startSpan('babel-loader')
return traceAsyncFn(span, async () => {
const filename = this.resourcePath
span.setAttribute('filename', filename)
let loaderOptions = loaderUtils.getOptions(this) || {}
let customOptions
if (overrides && overrides.customOptions) {
const result = await traceAsyncFn(
tracer.startSpan('loader-overrides-customoptions'),
async () =>
await overrides.customOptions.call(this, loaderOptions, {
source,
map: inputSourceMap,
})
)
customOptions = result.custom
loaderOptions = result.loader
}
// Standardize on 'sourceMaps' as the key passed through to Webpack, so that
// users may safely use either one alongside our default use of
// 'this.sourceMap' below without getting error about conflicting aliases.
if (
Object.prototype.hasOwnProperty.call(loaderOptions, 'sourceMap') &&
!Object.prototype.hasOwnProperty.call(loaderOptions, 'sourceMaps')
) {
loaderOptions = Object.assign({}, loaderOptions, {
sourceMaps: loaderOptions.sourceMap,
})
delete loaderOptions.sourceMap
}
const programmaticOptions = Object.assign({}, loaderOptions, {
filename,
inputSourceMap: inputSourceMap || undefined,
// Set the default sourcemap behavior based on Webpack's mapping flag,
// but allow users to override if they want.
sourceMaps:
loaderOptions.sourceMaps === undefined
? this.sourceMap
: loaderOptions.sourceMaps,
// Ensure that Webpack will get a full absolute path in the sourcemap
// so that it can properly map the module back to its internal cached
// modules.
sourceFileName: filename,
caller: {
name: 'babel-loader',
// Provide plugins with insight into webpack target.
// https://github.com/babel/babel-loader/issues/787
target: this.target,
// Webpack >= 2 supports ESM and dynamic import.
supportsStaticESM: true,
supportsDynamicImport: true,
// Webpack 5 supports TLA behind a flag. We enable it by default
// for Babel, and then webpack will throw an error if the experimental
// flag isn't enabled.
supportsTopLevelAwait: true,
...loaderOptions.caller,
},
})
// Remove loader related options
delete programmaticOptions.cacheDirectory
delete programmaticOptions.cacheIdentifier
const config = traceFn(
tracer.startSpan('babel-load-partial-config-async'),
() => {
return babel.loadPartialConfig(programmaticOptions)
}
)
if (config) {
let options = config.options
if (overrides && overrides.config) {
options = await traceAsyncFn(
tracer.startSpan('loader-overrides-config'),
async () =>
await overrides.config.call(this, config, {
source,
map: inputSourceMap,
customOptions,
})
)
}
if (options.sourceMaps === 'inline') {
// Babel has this weird behavior where if you set "inline", we
// inline the sourcemap, and set 'result.map = null'. This results
// in bad behavior from Babel since the maps get put into the code,
// which Webpack does not expect, and because the map we return to
// Webpack is null, which is also bad. To avoid that, we override the
// behavior here so "inline" just behaves like 'true'.
options.sourceMaps = true
}
const { cacheDirectory, cacheIdentifier } = loaderOptions
let result
if (cacheDirectory) {
result = await cache({
source,
options,
cacheDirectory,
cacheIdentifier,
cacheCompression: false,
})
} else {
result = await traceAsyncFn(
tracer.startSpan('transform', {
attributes: {
filename,
cache: 'DISABLED',
},
}),
async () => {
return transform(source, options)
}
)
}
// TODO: Babel should really provide the full list of config files that
// were used so that this can also handle files loaded with 'extends'.
if (typeof config.babelrc === 'string') {
this.addDependency(config.babelrc)
}
if (result) {
const { code, map } = result
return [code, map]
}
}
// If the file was ignored, pass through the original content.
return [source, inputSourceMap]
})
}

View file

@ -0,0 +1,29 @@
import { transform as _transform } from 'next/dist/compiled/babel/core'
import { promisify } from 'util'
import LoaderError from './Error'
const transform = promisify(_transform)
export default async function (source, options) {
let result
try {
result = await transform(source, options)
} catch (err) {
throw err.message && err.codeFrame ? new LoaderError(err) : err
}
if (!result) return null
// We don't return the full result here because some entries are not
// really serializable. For a full list of properties see here:
// https://github.com/babel/babel/blob/main/packages/babel-core/src/transformation/index.js
// For discussion on this topic see here:
// https://github.com/babel/babel-loader/pull/629
const { ast, code, map, metadata, sourceType } = result
if (map && (!map.sourcesContent || !map.sourcesContent.length)) {
map.sourcesContent = [source]
}
return { ast, code, map, metadata, sourceType }
}

View file

@ -1,4 +1,4 @@
import babelLoader from 'next/dist/compiled/babel-loader'
import babelLoader from './babel-loader/src/index'
import hash from 'next/dist/compiled/string-hash'
import { basename, join } from 'path'
import * as Log from '../../output/log'
@ -8,7 +8,7 @@ import * as Log from '../../output/log'
const cacheKey = 'babel-cache-' + 'o' + '-'
const nextBabelPreset = require('../../babel/preset')
module.exports = babelLoader.custom((babel) => {
const customBabelLoader = babelLoader((babel) => {
const presetItem = babel.createConfigItem(nextBabelPreset, {
type: 'preset',
})
@ -37,7 +37,6 @@ module.exports = babelLoader.custom((babel) => {
const loader = Object.assign(
opts.cache
? {
cacheCompression: false,
cacheDirectory: join(opts.distDir, 'cache', 'next-babel-loader'),
cacheIdentifier:
cacheKey +
@ -210,3 +209,5 @@ module.exports = babelLoader.custom((babel) => {
},
}
})
export default customBabelLoader

View file

@ -1,5 +1,6 @@
import { loader } from 'webpack'
import loaderUtils from 'loader-utils'
import { tracer, traceFn } from '../../tracer'
export type ClientPagesLoaderOptions = {
absolutePagePath: string
@ -7,9 +8,14 @@ export type ClientPagesLoaderOptions = {
}
const nextClientPagesLoader: loader.Loader = function () {
const span = tracer.startSpan('next-client-pages-loader')
return traceFn(span, () => {
const { absolutePagePath, page } = loaderUtils.getOptions(
this
) as ClientPagesLoaderOptions
span.setAttribute('absolutePagePath', absolutePagePath)
const stringifiedAbsolutePagePath = JSON.stringify(absolutePagePath)
const stringifiedPage = JSON.stringify(page)
@ -21,6 +27,7 @@ const nextClientPagesLoader: loader.Loader = function () {
}
]);
`
})
}
export default nextClientPagesLoader

View file

@ -11,6 +11,7 @@ import {
ROUTES_MANIFEST,
REACT_LOADABLE_MANIFEST,
} from '../../../../next-server/lib/constants'
import { tracer, traceFn } from '../../../tracer'
export type ServerlessLoaderQuery = {
page: string
@ -33,6 +34,8 @@ export type ServerlessLoaderQuery = {
}
const nextServerlessLoader: loader.Loader = function () {
const span = tracer.startSpan('next-serverless-loader')
return traceFn(span, () => {
const {
distDir,
absolutePagePath,
@ -55,10 +58,10 @@ const nextServerlessLoader: loader.Loader = function () {
typeof this.query === 'string' ? parse(this.query.substr(1)) : this.query
const buildManifest = join(distDir, BUILD_MANIFEST).replace(/\\/g, '/')
const reactLoadableManifest = join(distDir, REACT_LOADABLE_MANIFEST).replace(
/\\/g,
'/'
)
const reactLoadableManifest = join(
distDir,
REACT_LOADABLE_MANIFEST
).replace(/\\/g, '/')
const routesManifest = join(distDir, ROUTES_MANIFEST).replace(/\\/g, '/')
const escapedBuildId = escapeRegexp(buildId)
@ -194,6 +197,7 @@ const nextServerlessLoader: loader.Loader = function () {
export { renderReqToHTML, render }
`
}
})
}
export default nextServerlessLoader

View file

@ -14,6 +14,7 @@ import getRouteFromEntrypoint from '../../../next-server/server/get-route-from-e
import { ampFirstEntryNamesMap } from './next-drop-client-page-plugin'
import { Rewrite } from '../../../lib/load-custom-routes'
import { getSortedRoutes } from '../../../next-server/lib/router/utils'
import { tracer, traceFn } from '../../tracer'
// @ts-ignore: TODO: remove ignore when webpack 5 is stable
const { RawSource } = webpack.sources || sources
@ -30,6 +31,8 @@ function generateClientManifest(
assetMap: BuildManifest,
rewrites: Rewrite[]
): string {
const span = tracer.startSpan('NextJsBuildManifest-generateClientManifest')
return traceFn(span, () => {
const clientManifest: ClientBuildManifest = {
// TODO: update manifest type to include rewrites
__rewrites: rewrites as any,
@ -43,7 +46,9 @@ function generateClientManifest(
if (page === '/_app') return
// Filter out dependencies in the _app entry, because those will have already
// been loaded by the client prior to a navigation event
const filteredDeps = dependencies.filter((dep) => !appDependencies.has(dep))
const filteredDeps = dependencies.filter(
(dep) => !appDependencies.has(dep)
)
// The manifest can omit the page if it has no requirements
if (filteredDeps.length) {
@ -55,6 +60,7 @@ function generateClientManifest(
clientManifest.sortedPages = sortedPageKeys
return devalue(clientManifest)
})
}
function isJsFile(file: string): boolean {
@ -95,6 +101,8 @@ export default class BuildManifestPlugin {
}
createAssets(compilation: any, assets: any) {
const span = tracer.startSpan('NextJsBuildManifest-createassets')
return traceFn(span, () => {
const namedChunks: Map<string, CompilationType.Chunk> =
compilation.namedChunks
const assetMap: DeepMutable<BuildManifest> = {
@ -124,7 +132,9 @@ export default class BuildManifestPlugin {
isJsFile
)
const polyfillChunk = namedChunks.get(CLIENT_STATIC_FILES_RUNTIME_POLYFILLS)
const polyfillChunk = namedChunks.get(
CLIENT_STATIC_FILES_RUNTIME_POLYFILLS
)
// Create a separate entry for polyfills
assetMap.polyfillFiles = getFilesArray(polyfillChunk?.files).filter(
@ -134,7 +144,9 @@ export default class BuildManifestPlugin {
const reactRefreshChunk = namedChunks.get(
CLIENT_STATIC_FILES_RUNTIME_REACT_REFRESH
)
assetMap.devFiles = getFilesArray(reactRefreshChunk?.files).filter(isJsFile)
assetMap.devFiles = getFilesArray(reactRefreshChunk?.files).filter(
isJsFile
)
for (const entrypoint of compilation.entrypoints.values()) {
const isAmpRuntime = entrypoint.name === CLIENT_STATIC_FILES_RUNTIME_AMP
@ -202,6 +214,7 @@ export default class BuildManifestPlugin {
)
return assets
})
}
apply(compiler: Compiler) {

File diff suppressed because one or more lines are too long

View file

@ -1 +0,0 @@
{"name":"babel-loader","main":"index.js","author":"Luis Couto <hello@luiscouto.pt>","license":"MIT"}

View file

@ -1 +1 @@
module.exports=(()=>{var r={773:(r,e,t)=>{var s=t(622);r.exports=function(r,e){if(e){var t=e.map(function(e){return s.resolve(r,e)})}else{var t=r}var n=t.slice(1).reduce(function(r,e){if(!e.match(/^([A-Za-z]:)?\/|\\/)){throw new Error("relative path without a basedir")}var t=e.split(/\/+|\\+/);for(var s=0;r[s]===t[s]&&s<Math.min(r.length,t.length);s++);return r.slice(0,s)},t[0].split(/\/+|\\+/));return n.length>1?n.join("/"):"/"}},449:(r,e,t)=>{"use strict";const s=t(622);const n=t(747);const o=t(773);const c=t(402);const i=t(270);const{env:a,cwd:u}=process;const d=r=>{try{n.accessSync(r,n.constants.W_OK);return true}catch(r){return false}};function useDirectory(r,e){if(e.create){i.sync(r)}if(e.thunk){return(...e)=>s.join(r,...e)}return r}function getNodeModuleDirectory(r){const e=s.join(r,"node_modules");if(!d(e)&&(n.existsSync(e)||!d(s.join(r)))){return}return e}r.exports=((r={})=>{if(a.CACHE_DIR&&!["true","false","1","0"].includes(a.CACHE_DIR)){return useDirectory(s.join(a.CACHE_DIR,"find-cache-dir"),r)}let{cwd:e=u()}=r;if(r.files){e=o(e,r.files)}e=c.sync(e);if(!e){return}const t=getNodeModuleDirectory(e);if(!t){return undefined}return useDirectory(s.join(e,"node_modules",".cache",r.name),r)})},270:(r,e,t)=>{"use strict";const s=t(747);const n=t(622);const{promisify:o}=t(669);const c=t(519);const i=c.satisfies(process.version,">=10.12.0");const a=r=>{if(process.platform==="win32"){const e=/[<>:"|?*]/.test(r.replace(n.parse(r).root,""));if(e){const e=new Error(`Path contains invalid characters: ${r}`);e.code="EINVAL";throw e}}};const u=r=>{const e={mode:511&~process.umask(),fs:s};return{...e,...r}};const d=r=>{const e=new Error(`operation not permitted, mkdir '${r}'`);e.code="EPERM";e.errno=-4048;e.path=r;e.syscall="mkdir";return e};const f=async(r,e)=>{a(r);e=u(e);const t=o(e.fs.mkdir);const c=o(e.fs.stat);if(i&&e.fs.mkdir===s.mkdir){const s=n.resolve(r);await t(s,{mode:e.mode,recursive:true});return s}const f=async r=>{try{await t(r,e.mode);return r}catch(e){if(e.code==="EPERM"){throw e}if(e.code==="ENOENT"){if(n.dirname(r)===r){throw d(r)}if(e.message.includes("null bytes")){throw e}await f(n.dirname(r));return f(r)}try{const t=await c(r);if(!t.isDirectory()){throw new Error("The path is not a directory")}}catch(r){throw e}return r}};return f(n.resolve(r))};r.exports=f;r.exports.sync=((r,e)=>{a(r);e=u(e);if(i&&e.fs.mkdirSync===s.mkdirSync){const t=n.resolve(r);s.mkdirSync(t,{mode:e.mode,recursive:true});return t}const t=r=>{try{e.fs.mkdirSync(r,e.mode)}catch(s){if(s.code==="EPERM"){throw s}if(s.code==="ENOENT"){if(n.dirname(r)===r){throw d(r)}if(s.message.includes("null bytes")){throw s}t(n.dirname(r));return t(r)}try{if(!e.fs.statSync(r).isDirectory()){throw new Error("The path is not a directory")}}catch(r){throw s}}return r};return t(n.resolve(r))})},402:(r,e,t)=>{"use strict";const s=t(622);const n=t(442);const o=async r=>{const e=await n("package.json",{cwd:r});return e&&s.dirname(e)};r.exports=o;r.exports.default=o;r.exports.sync=(r=>{const e=n.sync("package.json",{cwd:r});return e&&s.dirname(e)})},747:r=>{"use strict";r.exports=require("fs")},442:r=>{"use strict";r.exports=require("next/dist/compiled/find-up")},519:r=>{"use strict";r.exports=require("next/dist/compiled/semver")},622:r=>{"use strict";r.exports=require("path")},669:r=>{"use strict";r.exports=require("util")}};var e={};function __webpack_require__(t){if(e[t]){return e[t].exports}var s=e[t]={exports:{}};var n=true;try{r[t](s,s.exports,__webpack_require__);n=false}finally{if(n)delete e[t]}return s.exports}__webpack_require__.ab=__dirname+"/";return __webpack_require__(449)})();
module.exports=(()=>{var r={773:(r,e,t)=>{var s=t(622);r.exports=function(r,e){if(e){var t=e.map(function(e){return s.resolve(r,e)})}else{var t=r}var n=t.slice(1).reduce(function(r,e){if(!e.match(/^([A-Za-z]:)?\/|\\/)){throw new Error("relative path without a basedir")}var t=e.split(/\/+|\\+/);for(var s=0;r[s]===t[s]&&s<Math.min(r.length,t.length);s++);return r.slice(0,s)},t[0].split(/\/+|\\+/));return n.length>1?n.join("/"):"/"}},430:(r,e,t)=>{"use strict";const s=t(622);const n=t(747);const o=t(773);const c=t(227);const i=t(618);const{env:a,cwd:u}=process;const d=r=>{try{n.accessSync(r,n.constants.W_OK);return true}catch(r){return false}};function useDirectory(r,e){if(e.create){i.sync(r)}if(e.thunk){return(...e)=>s.join(r,...e)}return r}function getNodeModuleDirectory(r){const e=s.join(r,"node_modules");if(!d(e)&&(n.existsSync(e)||!d(s.join(r)))){return}return e}r.exports=((r={})=>{if(a.CACHE_DIR&&!["true","false","1","0"].includes(a.CACHE_DIR)){return useDirectory(s.join(a.CACHE_DIR,"find-cache-dir"),r)}let{cwd:e=u()}=r;if(r.files){e=o(e,r.files)}e=c.sync(e);if(!e){return}const t=getNodeModuleDirectory(e);if(!t){return undefined}return useDirectory(s.join(e,"node_modules",".cache",r.name),r)})},618:(r,e,t)=>{"use strict";const s=t(747);const n=t(622);const{promisify:o}=t(669);const c=t(519);const i=c.satisfies(process.version,">=10.12.0");const a=r=>{if(process.platform==="win32"){const e=/[<>:"|?*]/.test(r.replace(n.parse(r).root,""));if(e){const e=new Error(`Path contains invalid characters: ${r}`);e.code="EINVAL";throw e}}};const u=r=>{const e={mode:511&~process.umask(),fs:s};return{...e,...r}};const d=r=>{const e=new Error(`operation not permitted, mkdir '${r}'`);e.code="EPERM";e.errno=-4048;e.path=r;e.syscall="mkdir";return e};const f=async(r,e)=>{a(r);e=u(e);const t=o(e.fs.mkdir);const c=o(e.fs.stat);if(i&&e.fs.mkdir===s.mkdir){const s=n.resolve(r);await t(s,{mode:e.mode,recursive:true});return s}const f=async r=>{try{await t(r,e.mode);return r}catch(e){if(e.code==="EPERM"){throw e}if(e.code==="ENOENT"){if(n.dirname(r)===r){throw d(r)}if(e.message.includes("null bytes")){throw e}await f(n.dirname(r));return f(r)}try{const t=await c(r);if(!t.isDirectory()){throw new Error("The path is not a directory")}}catch(r){throw e}return r}};return f(n.resolve(r))};r.exports=f;r.exports.sync=((r,e)=>{a(r);e=u(e);if(i&&e.fs.mkdirSync===s.mkdirSync){const t=n.resolve(r);s.mkdirSync(t,{mode:e.mode,recursive:true});return t}const t=r=>{try{e.fs.mkdirSync(r,e.mode)}catch(s){if(s.code==="EPERM"){throw s}if(s.code==="ENOENT"){if(n.dirname(r)===r){throw d(r)}if(s.message.includes("null bytes")){throw s}t(n.dirname(r));return t(r)}try{if(!e.fs.statSync(r).isDirectory()){throw new Error("The path is not a directory")}}catch(r){throw s}}return r};return t(n.resolve(r))})},227:(r,e,t)=>{"use strict";const s=t(622);const n=t(442);const o=async r=>{const e=await n("package.json",{cwd:r});return e&&s.dirname(e)};r.exports=o;r.exports.default=o;r.exports.sync=(r=>{const e=n.sync("package.json",{cwd:r});return e&&s.dirname(e)})},747:r=>{"use strict";r.exports=require("fs")},442:r=>{"use strict";r.exports=require("next/dist/compiled/find-up")},519:r=>{"use strict";r.exports=require("next/dist/compiled/semver")},622:r=>{"use strict";r.exports=require("path")},669:r=>{"use strict";r.exports=require("util")}};var e={};function __webpack_require__(t){if(e[t]){return e[t].exports}var s=e[t]={exports:{}};var n=true;try{r[t](s,s.exports,__webpack_require__);n=false}finally{if(n)delete e[t]}return s.exports}__webpack_require__.ab=__dirname+"/";return __webpack_require__(430)})();

View file

@ -171,7 +171,6 @@
"ast-types": "0.13.2",
"async-retry": "1.2.3",
"async-sema": "3.0.0",
"babel-loader": "8.1.0",
"babel-plugin-dynamic-import-node": "2.3.3",
"cacache": "15.0.5",
"cache-loader": "4.1.0",

View file

@ -125,14 +125,6 @@ export async function ncc_babel_bundle_packages(task, opts) {
.target('compiled/babel/')
}
// eslint-disable-next-line camelcase
externals['babel-loader'] = 'next/dist/compiled/babel-loader'
export async function ncc_babel_loader(task, opts) {
await task
.source(opts.src || relative(__dirname, require.resolve('babel-loader')))
.ncc({ packageName: 'babel-loader', externals })
.target('compiled/babel-loader')
}
// eslint-disable-next-line camelcase
externals['cacache'] = 'next/dist/compiled/cacache'
export async function ncc_cacache(task, opts) {
@ -551,7 +543,6 @@ export async function ncc(task) {
'ncc_async_sema',
'ncc_babel_bundle',
'ncc_babel_bundle_packages',
'ncc_babel_loader',
'ncc_cacache',
'ncc_cache_loader',
'ncc_ci_info',

View file

@ -6,7 +6,13 @@ process.env.NODE_ENV = 'production'
require('next/dist/build/babel/preset')
process.env.NODE_ENV = NODE_ENV
const loader = require('next/dist/build/webpack/loaders/next-babel-loader')
function interopRequireDefault(mod) {
return mod.default || mod
}
const loader = interopRequireDefault(
require('next/dist/build/webpack/loaders/next-babel-loader')
)
const os = require('os')
const path = require('path')

View file

@ -3865,16 +3865,6 @@ babel-jest@^26.0.1:
graceful-fs "^4.2.4"
slash "^3.0.0"
babel-loader@8.1.0:
version "8.1.0"
resolved "https://registry.yarnpkg.com/babel-loader/-/babel-loader-8.1.0.tgz#c611d5112bd5209abe8b9fa84c3e4da25275f1c3"
dependencies:
find-cache-dir "^2.1.0"
loader-utils "^1.4.0"
mkdirp "^0.5.3"
pify "^4.0.1"
schema-utils "^2.6.5"
babel-plugin-dynamic-import-node@2.3.3, babel-plugin-dynamic-import-node@^2.3.3:
version "2.3.3"
resolved "https://registry.yarnpkg.com/babel-plugin-dynamic-import-node/-/babel-plugin-dynamic-import-node-2.3.3.tgz#84fda19c976ec5c6defef57f9427b3def66e17a3"
@ -9857,7 +9847,7 @@ loader-utils@2.0.0, loader-utils@^2.0.0:
emojis-list "^3.0.0"
json5 "^2.1.2"
loader-utils@^1.0.0, loader-utils@^1.0.1, loader-utils@^1.0.2, loader-utils@^1.1.0, loader-utils@^1.2.3, loader-utils@^1.4.0:
loader-utils@^1.0.0, loader-utils@^1.0.1, loader-utils@^1.0.2, loader-utils@^1.1.0, loader-utils@^1.2.3:
version "1.4.0"
resolved "https://registry.yarnpkg.com/loader-utils/-/loader-utils-1.4.0.tgz#c579b5e34cb34b1a74edc6c1fb36bfa371d5a613"
dependencies: