Add stats config option (#21761)

This adds a config to output webpack's stats
This commit is contained in:
JJ Kasper 2021-02-02 09:39:39 -06:00 committed by GitHub
parent b6c3d9bff3
commit 523537178c
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
12 changed files with 124 additions and 0 deletions

View file

@ -43,6 +43,7 @@ import { build as buildConfiguration } from './webpack/config'
import { __overrideCssConfiguration } from './webpack/config/blocks/css/overrideCssConfiguration'
import { pluginLoaderOptions } from './webpack/loaders/next-plugin-loader'
import BuildManifestPlugin from './webpack/plugins/build-manifest-plugin'
import BuildStatsPlugin from './webpack/plugins/build-stats-plugin'
import ChunkNamesPlugin from './webpack/plugins/chunk-names-plugin'
import { CssMinimizerPlugin } from './webpack/plugins/css-minimizer-plugin'
import { JsConfigPathsPlugin } from './webpack/plugins/jsconfig-paths-plugin'
@ -1109,6 +1110,11 @@ export default async function getBaseWebpackConfig(
buildId,
rewrites,
}),
!isServer &&
config.experimental.stats &&
new BuildStatsPlugin({
distDir,
}),
new ProfilingPlugin(),
config.experimental.optimizeFonts &&
!dev &&

View file

@ -0,0 +1,48 @@
import fs from 'fs'
import path from 'path'
// @ts-ignore no types package
import bfj from 'next/dist/compiled/bfj'
import { spans } from './profiling-plugin'
import { webpack } from 'next/dist/compiled/webpack/webpack'
import { tracer, traceAsyncFn } from '../../tracer'
// This plugin creates a stats.json for a build when enabled
export default class BuildStatsPlugin {
private distDir: string
constructor(options: { distDir: string }) {
this.distDir = options.distDir
}
apply(compiler: webpack.Compiler) {
compiler.hooks.done.tapAsync(
'NextJsBuildStats',
async (stats, callback) => {
tracer.withSpan(spans.get(compiler), async () => {
try {
const writeStatsSpan = tracer.startSpan('NextJsBuildStats')
await traceAsyncFn(writeStatsSpan, () => {
return new Promise((resolve, reject) => {
const statsJson = stats.toJson({
source: false,
})
const fileStream = fs.createWriteStream(
path.join(this.distDir, 'next-stats.json')
)
const jsonStream = bfj.streamify(statsJson)
jsonStream.pipe(fileStream)
jsonStream.on('error', reject)
fileStream.on('error', reject)
jsonStream.on('dataError', reject)
fileStream.on('close', resolve)
})
})
callback()
} catch (err) {
callback(err)
}
})
}
)
}
}

File diff suppressed because one or more lines are too long

View file

@ -0,0 +1 @@
{"name":"bfj","main":"index.js","author":"Phil Booth (https://gitlab.com/philbooth)","license":"MIT"}

View file

@ -87,6 +87,7 @@ const defaultConfig: NextConfig = {
optimizeCss: false,
scrollRestoration: false,
scriptLoader: false,
stats: !!process.env.VERCEL_ANALYTICS_ID,
},
future: {
strictPostcssConfiguration: false,

View file

@ -178,6 +178,7 @@
"babel-plugin-dynamic-import-node": "2.3.3",
"babel-plugin-transform-define": "2.0.0",
"babel-plugin-transform-react-remove-prop-types": "0.4.24",
"bfj": "7.0.2",
"cacache": "15.0.5",
"cache-loader": "4.1.0",
"ci-info": "watson/ci-info#f43f6a1cefff47fb361c88cf4b943fdbcaafe540",

View file

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

View file

@ -0,0 +1,5 @@
module.exports = {
experimental: {
stats: true,
},
}

View file

@ -0,0 +1,3 @@
export default function Index(props) {
return <p>Hello world</p>
}

View file

@ -0,0 +1,20 @@
/* eslint-env jest */
import fs from 'fs-extra'
import { join } from 'path'
import { nextBuild } from 'next-test-utils'
jest.setTimeout(1000 * 60 * 1)
const appDir = join(__dirname, '../')
const statsPath = join(appDir, '.next/next-stats.json')
describe('Build Stats', () => {
it('outputs next-stats.json when enabled', async () => {
await nextBuild(appDir)
expect(await fs.pathExists(statsPath)).toBe(true)
const statsData = await fs.readFile(statsPath, 'utf8')
JSON.parse(statsData)
})
})

View file

@ -782,6 +782,10 @@ describe('Production Usage', () => {
expect(existsSync(join(appDir, '.next', 'profile-events.json'))).toBe(false)
})
it('should not emit stats', async () => {
expect(existsSync(join(appDir, '.next', 'next-stats.json'))).toBe(false)
})
it('should contain the Next.js version in window export', async () => {
let browser
try {

View file

@ -4016,6 +4016,16 @@ before-after-hook@^2.0.0:
version "2.1.0"
resolved "https://registry.yarnpkg.com/before-after-hook/-/before-after-hook-2.1.0.tgz#b6c03487f44e24200dd30ca5e6a1979c5d2fb635"
bfj@7.0.2:
version "7.0.2"
resolved "https://registry.yarnpkg.com/bfj/-/bfj-7.0.2.tgz#1988ce76f3add9ac2913fd8ba47aad9e651bfbb2"
integrity sha512-+e/UqUzwmzJamNF50tBV6tZPTORow7gQ96iFow+8b562OdMpEK0BcJEq2OSPEDmAbSMBQ7PKZ87ubFkgxpYWgw==
dependencies:
bluebird "^3.5.5"
check-types "^11.1.1"
hoopy "^0.1.4"
tryer "^1.0.1"
big.js@^5.2.2:
version "5.2.2"
resolved "https://registry.yarnpkg.com/big.js/-/big.js-5.2.2.tgz#65f0af382f578bcdc742bd9c281e9cb2d7768328"
@ -4619,6 +4629,11 @@ chardet@^0.7.0:
version "0.7.0"
resolved "https://registry.yarnpkg.com/chardet/-/chardet-0.7.0.tgz#90094849f0937f2eedc2425d0d28a9e5f0cbad9e"
check-types@^11.1.1:
version "11.1.2"
resolved "https://registry.yarnpkg.com/check-types/-/check-types-11.1.2.tgz#86a7c12bf5539f6324eb0e70ca8896c0e38f3e2f"
integrity sha512-tzWzvgePgLORb9/3a0YenggReLKAIb2owL03H2Xdoe5pKcUyWRSEQ8xfCar8t2SIAuEDwtmx2da1YB52YuHQMQ==
cheerio@0.22.0:
version "0.22.0"
resolved "https://registry.yarnpkg.com/cheerio/-/cheerio-0.22.0.tgz#a9baa860a3f9b595a6b81b1a86873121ed3a269e"
@ -7877,6 +7892,11 @@ homedir-polyfill@^1.0.0:
dependencies:
parse-passwd "^1.0.0"
hoopy@^0.1.4:
version "0.1.4"
resolved "https://registry.yarnpkg.com/hoopy/-/hoopy-0.1.4.tgz#609207d661100033a9a9402ad3dea677381c1b1d"
integrity sha512-HRcs+2mr52W0K+x8RzcLzuPPmVIKMSv97RGHy0Ea9y/mpcaK+xTrjICA04KAHi4GRzxliNqNJEFYWHghy3rSfQ==
hosted-git-info@^2.1.4, hosted-git-info@^2.7.1:
version "2.8.5"
resolved "https://registry.yarnpkg.com/hosted-git-info/-/hosted-git-info-2.8.5.tgz#759cfcf2c4d156ade59b0b2dfabddc42a6b9c70c"
@ -15507,6 +15527,11 @@ trough@^1.0.0:
dependencies:
glob "^7.1.2"
tryer@^1.0.1:
version "1.0.1"
resolved "https://registry.yarnpkg.com/tryer/-/tryer-1.0.1.tgz#f2c85406800b9b0f74c9f7465b81eaad241252f8"
integrity sha512-c3zayb8/kWWpycWYg87P71E1S1ZL6b6IJxfb5fvsUgsf0S2MVGaDhDXXjDMpdCpfWXqptc+4mXwmiy1ypXqRAA==
ts-pnp@^1.1.6:
version "1.2.0"
resolved "https://registry.yarnpkg.com/ts-pnp/-/ts-pnp-1.2.0.tgz#a500ad084b0798f1c3071af391e65912c86bca92"