Skip to content
34 changes: 34 additions & 0 deletions .github/workflows/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -721,3 +721,37 @@ jobs:
- run: |
echo github.ref: ${{ github.ref }}
echo isV3: ${{ github.ref == 'refs/heads/main' }}
analyze:
runs-on: ubuntu-latest
needs: [changes, build]
timeout-minutes: 5
permissions:
contents: read # for checkout repository
actions: read # for fetching base branch bundle stats
pull-requests: write # for comments
steps:
- uses: actions/checkout@v4

- name: Node setup
uses: ./.github/actions/setup
with:
node-version: ${{ env.NODE_VERSION }}
pnpm-version: ${{ env.PNPM_VERSION }}
pnpm-run-install: false
pnpm-restore-cache: false # Full build is restored below
pnpm-install-cache-key: pnpm-store-${{ hashFiles('**/pnpm-lock.yaml') }}

- name: Restore build
uses: actions/cache@v4
with:
path: ./*
key: ${{ github.sha }}-${{ github.run_number }}

- run: pnpm run build:bundle-for-analysis # Esbuild packages that haven't already been built in the build step for the purpose of analyzing bundle size
env:
DO_NOT_TRACK: 1 # Disable Turbopack telemetry

- name: Analyze esbuild bundle size
uses: exoego/esbuild-bundle-analyzer@v1
with:
metafiles: 'packages/payload/meta_index.json,packages/payload/meta_shared.json,packages/ui/meta_client.json,packages/ui/meta_shared.json,packages/next/meta_index.json,packages/richtext-lexical/meta_client.json'
5 changes: 5 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,11 @@ meta_server.json
meta_index.json
meta_shared.json

packages/payload/esbuild
packages/ui/esbuild
packages/next/esbuild
packages/richtext-lexical/esbuild

.turbo

# Ignore test directory media folder/files
Expand Down
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
"build:all": "turbo build --filter \"!blank\" --filter \"!website\"",
"build:app": "next build",
"build:app:analyze": "cross-env ANALYZE=true next build",
"build:bundle-for-analysis": "turbo run build:bundle-for-analysis",
"build:clean": "pnpm clean:build",
"build:core": "turbo build --filter \"!@payloadcms/plugin-*\" --filter \"!@payloadcms/storage-*\" --filter \"!blank\" --filter \"!website\"",
"build:core:force": "pnpm clean:build && pnpm build:core --no-cache --force",
Expand Down
32 changes: 32 additions & 0 deletions packages/next/bundle.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
import * as esbuild from 'esbuild'
import fs from 'fs'
import { sassPlugin } from 'esbuild-sass-plugin'
import path from 'path'
import { fileURLToPath } from 'url'
const filename = fileURLToPath(import.meta.url)
const dirname = path.dirname(filename)

const directoryArg = process.argv[2] || 'dist'

async function build() {
const resultIndex = await esbuild.build({
entryPoints: ['dist/esbuildEntry.js'],
bundle: true,
platform: 'node',
format: 'esm',
outfile: `${directoryArg}/index.js`,
splitting: false,
external: ['@payloadcms/ui', 'payload', '@payloadcms/translations', '@payloadcms/graphql'],
minify: true,
metafile: true,
tsconfig: path.resolve(dirname, './tsconfig.json'),
// plugins: [commonjs()],
sourcemap: true,
plugins: [sassPlugin({ css: 'external' })],
})
console.log('payload server bundled successfully')

fs.writeFileSync('meta_index.json', JSON.stringify(resultIndex.metafile))
}

await build()
12 changes: 12 additions & 0 deletions packages/next/eslint.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,18 @@ export const index = [
},
},
},
{
languageOptions: {
parserOptions: {
...rootParserOptions,
tsconfigRootDir: import.meta.dirname,
projectService: {
// See comment in packages/eslint-config/index.mjs
allowDefaultProject: ['bundleScss.js', 'bundle.js', 'babel.config.cjs'],
},
},
},
},
]

export default index
1 change: 1 addition & 0 deletions packages/next/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,7 @@
"scripts": {
"build": "pnpm build:reactcompiler",
"build:babel": "rm -rf dist_optimized && babel dist --out-dir dist_optimized --source-maps --extensions .ts,.js,.tsx,.jsx,.cjs,.mjs && rm -rf dist && mv dist_optimized dist",
"build:bundle-for-analysis": "rm -rf dist && rm -rf tsconfig.tsbuildinfo && pnpm build:swc && pnpm build:babel && pnpm copyfiles && node ./bundle.js esbuild",
"build:cjs": "swc ./src/withPayload.js -o ./dist/cjs/withPayload.cjs --config-file .swcrc-cjs --strip-leading-paths",
"build:esbuild": "node bundleScss.js",
"build:reactcompiler": "rm -rf dist && rm -rf tsconfig.tsbuildinfo && pnpm build:swc && pnpm build:babel && pnpm copyfiles && pnpm build:types && pnpm build:esbuild && pnpm build:cjs",
Expand Down
11 changes: 7 additions & 4 deletions packages/payload/bundle.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,16 @@ import { fileURLToPath } from 'url'
const filename = fileURLToPath(import.meta.url)
const dirname = path.dirname(filename)

const directoryArg = process.argv[2] || 'dist'


async function build() {
const resultIndex = await esbuild.build({
entryPoints: ['src/index.ts'],
entryPoints: ['dist/index.js'],
bundle: true,
platform: 'node',
format: 'esm',
outfile: 'dist/index.js',
outfile: `${directoryArg}/index.js`,
splitting: false,
external: [
'lodash',
Expand All @@ -33,11 +36,11 @@ async function build() {
console.log('payload server bundled successfully')

const resultShared = await esbuild.build({
entryPoints: ['src/exports/shared.ts'],
entryPoints: ['dist/exports/shared.js'],
bundle: true,
platform: 'node',
format: 'esm',
outfile: 'dist/exports/shared.js',
outfile: `${directoryArg}/exports/shared.js`,
splitting: false,
external: [
'lodash',
Expand Down
4 changes: 2 additions & 2 deletions packages/payload/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -71,8 +71,8 @@
"bin.js"
],
"scripts": {
"build": "rimraf .dist && rimraf tsconfig.tsbuildinfo && pnpm copyfiles && pnpm build:types && pnpm build:swc && pnpm build:esbuild",
"build:esbuild": "echo skipping esbuild",
"build": "rimraf .dist && rimraf tsconfig.tsbuildinfo && pnpm copyfiles && pnpm build:types && pnpm build:swc && echo skipping esbuild",
"build:bundle-for-analysis": "node ./bundle.js esbuild",
"build:swc": "swc ./src -d ./dist --config-file .swcrc --strip-leading-paths",
"build:types": "tsc --emitDeclarationOnly --outDir dist",
"clean": "rimraf -g {dist,*.tsbuildinfo}",
Expand Down
27 changes: 17 additions & 10 deletions packages/richtext-lexical/bundle.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,10 @@ const filename = fileURLToPath(import.meta.url)
const dirname = path.dirname(filename)
import { sassPlugin } from 'esbuild-sass-plugin'

const directoryArg = process.argv[2] || 'dist'

const shouldSplit = process.argv.includes('--no-split') ? false : true

const removeCSSImports = {
name: 'remove-css-imports',
setup(build) {
Expand All @@ -19,42 +23,45 @@ const removeCSSImports = {
}

async function build() {
//create empty directoryArg/exports/client_optimized dir
await fs.promises.mkdir(`${directoryArg}/exports/client_optimized`, { recursive: true })

// Bundle only the .scss files into a single css file
await esbuild.build({
entryPoints: ['src/exports/cssEntry.ts'],
bundle: true,
minify: true,
outdir: 'dist/bundled_scss',
outdir: `${directoryArg}/bundled_scss`,
loader: { '.svg': 'dataurl' },
packages: 'external',
//external: ['*.svg'],
plugins: [sassPlugin({ css: 'external' })],
})

//create empty dist/exports/client_optimized dir
fs.mkdirSync('dist/exports/client_optimized')

try {
fs.renameSync('dist/bundled_scss/cssEntry.css', 'dist/field/bundled.css')
fs.copyFileSync('dist/field/bundled.css', 'dist/exports/client_optimized/bundled.css')
fs.rmSync('dist/bundled_scss', { recursive: true })
await fs.promises.rename(`${directoryArg}/bundled_scss/cssEntry.css`, `dist/field/bundled.css`)
fs.copyFileSync(
`dist/field/bundled.css`,
`${directoryArg}/exports/client_optimized/bundled.css`,
)
fs.rmSync(`${directoryArg}/bundled_scss`, { recursive: true })
} catch (err) {
console.error(`Error while renaming index.css: ${err}`)
throw err
}

console.log('dist/field/bundled.css bundled successfully')
console.log(`${directoryArg}/field/bundled.css bundled successfully`)

// Bundle `client.ts`
const resultClient = await esbuild.build({
entryPoints: ['dist/exports/client/index.js'],
bundle: true,
platform: 'browser',
format: 'esm',
outdir: 'dist/exports/client_optimized',
outdir: `${directoryArg}/exports/client_optimized`,
//outfile: 'index.js',
// IMPORTANT: splitting the client bundle means that the `use client` directive will be lost for every chunk
splitting: true,
splitting: shouldSplit,
external: [
'*.scss',
'*.css',
Expand Down
8 changes: 5 additions & 3 deletions packages/richtext-lexical/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -337,12 +337,14 @@
"scripts": {
"build": "pnpm build:reactcompiler",
"build:babel": "rm -rf dist_optimized && babel dist --out-dir dist_optimized --source-maps --extensions .ts,.js,.tsx,.jsx,.cjs,.mjs && rm -rf dist && mv dist_optimized dist",
"build:bundle-for-analysis": "rm -rf dist esbuild && rm -rf tsconfig.tsbuildinfo && pnpm build:swc && pnpm build:babel && pnpm copyfiles && pnpm build:esbuild esbuild --no-split",
"build:clean": "find . \\( -type d \\( -name build -o -name dist -o -name .cache \\) -o -type f -name tsconfig.tsbuildinfo \\) -exec rm -rf {} + && pnpm build",
"build:esbuild": "node bundle.js && rm -rf dist/exports/client && mv dist/exports/client_optimized dist/exports/client",
"build:reactcompiler": "rm -rf dist && rm -rf tsconfig.tsbuildinfo && pnpm build:swc && pnpm build:babel && pnpm copyfiles && pnpm build:esbuild && pnpm build:types",
"build:esbuild": "node bundle.js",
"build:esbuild:postprocess": "rm -rf dist/exports/client && mv dist/exports/client_optimized dist/exports/client",
"build:reactcompiler": "rm -rf dist && rm -rf tsconfig.tsbuildinfo && pnpm build:swc && pnpm build:babel && pnpm copyfiles && pnpm build:esbuild && pnpm build:esbuild:postprocess && pnpm build:types",
"build:swc": "swc ./src -d ./dist --config-file .swcrc --strip-leading-paths",
"build:types": "tsc --emitDeclarationOnly --outDir dist",
"build:without_reactcompiler": "rm -rf dist && rm -rf tsconfig.tsbuildinfo && pnpm copyfiles && pnpm build:types && pnpm build:swc && pnpm build:esbuild && rm -rf dist/exports/client && mv dist/exports/client_unoptimized dist/exports/client",
"build:without_reactcompiler": "rm -rf dist && rm -rf tsconfig.tsbuildinfo && pnpm copyfiles && pnpm build:types && pnpm build:swc && pnpm build:esbuild && pnpm build:esbuild:postproces && rm -rf dist/exports/client && mv dist/exports/client_unoptimized dist/exports/client",
"clean": "rimraf -g {dist,*.tsbuildinfo}",
"copyfiles": "copyfiles -u 1 \"src/**/*.{html,css,ttf,woff,woff2,eot,svg,jpg,png,json}\" dist/",
"lint": "eslint .",
Expand Down
19 changes: 14 additions & 5 deletions packages/ui/bundle.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,10 @@ const dirname = path.dirname(filename)
import { sassPlugin } from 'esbuild-sass-plugin'
import { commonjs } from '@hyrious/esbuild-plugin-commonjs'

const directoryArg = process.argv[2] || 'dist'

const shouldSplit = process.argv.includes('--no-split') ? false : true

const removeCSSImports = {
name: 'remove-css-imports',
setup(build) {
Expand Down Expand Up @@ -62,6 +66,11 @@ const useClientPlugin = {
}

async function build() {
// Create directoryArg if it doesn't exist
if (!fs.existsSync(directoryArg)) {
await fs.promises.mkdir(directoryArg, { recursive: true })
}

// Bundle only the .scss files into a single css file
await esbuild.build({
entryPoints: ['src/exports/client/index.ts'],
Expand All @@ -73,7 +82,7 @@ async function build() {
})

try {
fs.renameSync('dist-styles/index.css', 'dist/styles.css')
fs.renameSync('dist-styles/index.css', `${directoryArg}/styles.css`)
fs.rmdirSync('dist-styles', { recursive: true })
} catch (err) {
console.error(`Error while renaming index.css and dist-styles: ${err}`)
Expand All @@ -87,10 +96,10 @@ async function build() {
bundle: true,
platform: 'browser',
format: 'esm',
outdir: 'dist/exports/client_optimized',
outdir: `${directoryArg}/exports/client_optimized`,
//outfile: 'index.js',
// IMPORTANT: splitting the client bundle means that the `use client` directive will be lost for every chunk
splitting: true,
splitting: shouldSplit,
write: true, // required for useClientPlugin
banner: {
js: `// Workaround for react-datepicker and other cjs dependencies potentially inserting require("react") statements
Expand Down Expand Up @@ -142,11 +151,11 @@ function require(m) {
console.log('client.ts bundled successfully')

const resultShared = await esbuild.build({
entryPoints: ['src/exports/shared/index.ts'],
entryPoints: ['dist/exports/shared/index.js'],
bundle: true,
platform: 'node',
format: 'esm',
outdir: 'dist/exports/shared',
outdir: `${directoryArg}/exports/shared_optimized`,
//outfile: 'index.js',
// IMPORTANT: splitting the client bundle means that the `use client` directive will be lost for every chunk
splitting: false,
Expand Down
6 changes: 4 additions & 2 deletions packages/ui/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -121,8 +121,10 @@
"scripts": {
"build": "pnpm build:reactcompiler",
"build:babel": "rm -rf dist_optimized && babel dist --out-dir dist_optimized --source-maps --extensions .ts,.js,.tsx,.jsx,.cjs,.mjs && rm -rf dist && mv dist_optimized dist",
"build:esbuild": "node bundle.js && rm -rf dist/exports/client && mv dist/exports/client_optimized dist/exports/client",
"build:reactcompiler": "rm -rf dist && rm -rf tsconfig.tsbuildinfo && pnpm build:swc && pnpm build:babel && pnpm copyfiles && pnpm build:esbuild && pnpm build:types",
"build:bundle-for-analysis": "rm -rf dist && rm -rf tsconfig.tsbuildinfo && pnpm build:swc && pnpm build:babel && pnpm copyfiles && pnpm build:esbuild esbuild --no-split",
"build:esbuild": "node bundle.js",
"build:esbuild:postprocess": "rm -rf dist/exports/client && mv dist/exports/client_optimized dist/exports/client && rm -rf dist/exports/shared && mv dist/exports/shared_optimized dist/exports/shared",
"build:reactcompiler": "rm -rf dist esbuild && rm -rf tsconfig.tsbuildinfo && pnpm build:swc && pnpm build:babel && pnpm copyfiles && pnpm build:esbuild && pnpm build:esbuild:postprocess && pnpm build:types",
"build:remove-artifact": "rm dist/prod/index.js",
"build:swc": "swc ./src -d dist --config-file .swcrc --strip-leading-paths",
"build:types": "tsc --emitDeclarationOnly --outDir dist",
Expand Down
5 changes: 5 additions & 0 deletions turbo.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,11 @@
"dependsOn": ["^build"],
"outputs": ["./dist/**"]
},
"build:bundle-for-analysis": {
"cache": true,
"dependsOn": ["^build:bundle-for-analysis"],
"outputs": ["./esbuild/**"]
},
"dev": {
"cache": false
},
Expand Down
Loading