Skip to content

Commit

Permalink
Add CSS file to build output (#11145)
Browse files Browse the repository at this point in the history
* Remove filtering CSS from build output

* Add displaying page specific CSS files and including them in page size
  • Loading branch information
ijjk committed Mar 18, 2020
1 parent 88a6bb3 commit 836f68a
Show file tree
Hide file tree
Showing 3 changed files with 65 additions and 37 deletions.
100 changes: 63 additions & 37 deletions packages/next/build/utils.ts
Expand Up @@ -78,6 +78,15 @@ export async function printTreeView(
return chalk.red.bold(size)
}

const getCleanName = (fileName: string) =>
fileName
// Trim off `static/`
.replace(/^static\//, '')
// Re-add `static/` for root files
.replace(/^<buildId>/, 'static')
// Remove file hash
.replace(/[.-]([0-9a-z]{6})[0-9a-z]{14}(?=\.)/, '.$1')

const messages: [string, string, string][] = [
['Page', 'Size', 'First Load'].map(entry => chalk.underline(entry)) as [
string,
Expand All @@ -97,6 +106,14 @@ export async function printTreeView(
list = [...list, '/404']
}

const sizeData = await computeFromManifest(
buildManifest,
distPath,
buildId,
isModern,
pageInfos
)

const pageList = list
.slice()
.filter(
Expand Down Expand Up @@ -147,6 +164,24 @@ export async function printTreeView(
: '',
])

const uniqueCssFiles =
buildManifest.pages[item]?.filter(
file => file.endsWith('.css') && sizeData.uniqueFiles.includes(file)
) || []

if (uniqueCssFiles.length > 0) {
const contSymbol = i === arr.length - 1 ? ' ' : '├'

uniqueCssFiles.forEach((file, index, { length }) => {
const innerSymbol = index === length - 1 ? '└' : '├'
messages.push([
`${contSymbol} ${innerSymbol} ${getCleanName(file)}`,
prettyBytes(sizeData.sizeUniqueFiles[file]),
'',
])
})
}

if (pageInfo?.ssgPageRoutes?.length) {
const totalRoutes = pageInfo.ssgPageRoutes.length
const previewPages = totalRoutes === 4 ? 4 : 3
Expand All @@ -165,33 +200,22 @@ export async function printTreeView(
}
})

const sharedData = await getSharedSizes(
distPath,
buildManifest,
buildId,
isModern,
pageInfos
)
const sharedFilesSize = sizeData.sizeCommonFiles
const sharedFiles = sizeData.sizeCommonFile

messages.push(['+ shared by all', getPrettySize(sharedData.total), ''])
Object.keys(sharedData.files)
messages.push(['+ shared by all', getPrettySize(sharedFilesSize), ''])
Object.keys(sharedFiles)
.map(e => e.replace(buildId, '<buildId>'))
.sort()
.forEach((fileName, index, { length }) => {
const innerSymbol = index === length - 1 ? '└' : '├'

const originalName = fileName.replace('<buildId>', buildId)
const cleanName = fileName
// Trim off `static/`
.replace(/^static\//, '')
// Re-add `static/` for root files
.replace(/^<buildId>/, 'static')
// Remove file hash
.replace(/[.-]([0-9a-z]{6})[0-9a-z]{14}(?=\.)/, '.$1')
const cleanName = getCleanName(originalName)

messages.push([
` ${innerSymbol} ${cleanName}`,
prettyBytes(sharedData.files[originalName]),
prettyBytes(sharedFiles[originalName]),
'',
])
})
Expand Down Expand Up @@ -313,6 +337,7 @@ type BuildManifestShape = { pages: { [k: string]: string[] } }
type ComputeManifestShape = {
commonFiles: string[]
uniqueFiles: string[]
sizeUniqueFiles: { [file: string]: number }
sizeCommonFile: { [file: string]: number }
sizeCommonFiles: number
}
Expand Down Expand Up @@ -341,6 +366,9 @@ async function computeFromManifest(
let expected = 0
const files = new Map<string, number>()
Object.keys(manifest.pages).forEach(key => {
// prevent duplicate '/' and '/index'
if (key === '/index') return

if (key === '/_polyfills') {
return
}
Expand All @@ -357,8 +385,6 @@ async function computeFromManifest(
++expected
manifest.pages[key].forEach(file => {
if (
// Filter out CSS
!file.endsWith('.js') ||
// Select Modern or Legacy scripts
file.endsWith('.module.js') !== isModern
) {
Expand Down Expand Up @@ -403,9 +429,25 @@ async function computeFromManifest(
stats = []
}

let uniqueStats: [string, number][]
try {
uniqueStats = await Promise.all(
uniqueFiles.map(
async f =>
[f, await fsStatGzip(path.join(distPath, f))] as [string, number]
)
)
} catch (_) {
uniqueStats = []
}

lastCompute = {
commonFiles,
uniqueFiles,
sizeUniqueFiles: uniqueStats.reduce(
(obj, n) => Object.assign(obj, { [n[0]]: n[1] }),
{}
),
sizeCommonFile: stats.reduce(
(obj, n) => Object.assign(obj, { [n[0]]: n[1] }),
{}
Expand Down Expand Up @@ -435,23 +477,6 @@ function sum(a: number[]): number {
return a.reduce((size, stat) => size + stat, 0)
}

export async function getSharedSizes(
distPath: string,
buildManifest: BuildManifestShape,
buildId: string,
isModern: boolean,
pageInfos: Map<string, PageInfo>
): Promise<{ total: number; files: { [page: string]: number } }> {
const data = await computeFromManifest(
buildManifest,
distPath,
buildId,
isModern,
pageInfos
)
return { total: data.sizeCommonFiles, files: data.sizeCommonFile }
}

export async function getPageSizeInKb(
page: string,
distPath: string,
Expand All @@ -467,7 +492,8 @@ export async function getPageSizeInKb(
)

const fnFilterModern = (entry: string) =>
entry.endsWith('.js') && entry.endsWith('.module.js') === isModern
(entry.endsWith('.js') && entry.endsWith('.module.js') === isModern) ||
entry.endsWith('.css')

const pageFiles = (buildManifest.pages[page] || []).filter(fnFilterModern)
const appFiles = (buildManifest.pages['/_app'] || []).filter(fnFilterModern)
Expand Down
1 change: 1 addition & 0 deletions test/integration/css-modules/test/index.test.js
Expand Up @@ -40,6 +40,7 @@ describe('Basic CSS Module Support', () => {
it('should have compiled successfully', () => {
expect(code).toBe(0)
expect(stdout).toMatch(/Compiled successfully/)
expect(stdout).toContain('.css')
})

it(`should've emitted a single CSS file`, async () => {
Expand Down
1 change: 1 addition & 0 deletions test/integration/css/test/index.test.js
Expand Up @@ -819,6 +819,7 @@ describe('CSS Support', () => {
})
expect(code).toBe(0)
expect(stdout).toMatch(/Compiled successfully/)
expect(stdout).toContain('.css')
})

it(`should've compiled and prefixed`, async () => {
Expand Down

0 comments on commit 836f68a

Please sign in to comment.