chore(scripts/build): refactor plugins to own files
This commit is contained in:
parent
43ea84de29
commit
f8567c6e68
4 changed files with 169 additions and 159 deletions
165
scripts/build.ts
165
scripts/build.ts
|
|
@ -1,13 +1,13 @@
|
||||||
import { transform } from '@swc/core'
|
|
||||||
import { $, main } from 'bun'
|
import { $, main } from 'bun'
|
||||||
import chalk from 'chalk'
|
import chalk from 'chalk'
|
||||||
import { existsSync } from 'fs'
|
|
||||||
import { exists, mkdir, readdir, rm, writeFile } from 'fs/promises'
|
import { exists, mkdir, readdir, rm, writeFile } from 'fs/promises'
|
||||||
import { parse } from 'path'
|
import { parse } from 'path'
|
||||||
import { rolldown } from 'rolldown'
|
import { rolldown } from 'rolldown'
|
||||||
import { aliasPlugin, importGlobPlugin } from 'rolldown/experimental'
|
import { importGlobPlugin } from 'rolldown/experimental'
|
||||||
import pkg from '../package.json'
|
import pkg from '../package.json'
|
||||||
import type { OutputChunk, RolldownPlugin } from 'rolldown'
|
import hermesSwcPlugin from './plugins/hermes-swc'
|
||||||
|
import hermesCPlugin from './plugins/hermesc'
|
||||||
|
import shimAliases from './plugins/shim-aliases'
|
||||||
|
|
||||||
const ShimsDir = `${import.meta.dir}/../shims`
|
const ShimsDir = `${import.meta.dir}/../shims`
|
||||||
const AssetsDir = `${import.meta.dir}/../src/assets`
|
const AssetsDir = `${import.meta.dir}/../src/assets`
|
||||||
|
|
@ -86,38 +86,9 @@ export default async function build(dev = Dev, log = true) {
|
||||||
__BUILD_FLAG_LOG_PROMISE_REJECTIONS__: String(dev),
|
__BUILD_FLAG_LOG_PROMISE_REJECTIONS__: String(dev),
|
||||||
},
|
},
|
||||||
plugins: [
|
plugins: [
|
||||||
aliasPlugin({
|
shimAliases(ShimsDir),
|
||||||
entries: [
|
|
||||||
{
|
|
||||||
find: 'react/jsx-runtime',
|
|
||||||
replacement: `${ShimsDir}/react~jsx-runtime.ts`,
|
|
||||||
},
|
|
||||||
// Do not move React to the top!
|
|
||||||
// If you do that, react/jsx-runtime would resolve to ${ShimsDir}/react.ts/jsx-runtime instead.
|
|
||||||
{
|
|
||||||
find: 'react',
|
|
||||||
replacement: `${ShimsDir}/react.ts`,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
find: 'react-native',
|
|
||||||
replacement: `${ShimsDir}/react-native.ts`,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
find: '@react-navigation/native',
|
|
||||||
replacement: `${ShimsDir}/@react-navigation~native.ts`,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
find: '@react-navigation/stack',
|
|
||||||
replacement: `${ShimsDir}/@react-navigation~stack.ts`,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
find: '@shopify/flash-list',
|
|
||||||
replacement: `${ShimsDir}/@shopify~flash-list.ts`,
|
|
||||||
},
|
|
||||||
],
|
|
||||||
}),
|
|
||||||
importGlobPlugin(),
|
importGlobPlugin(),
|
||||||
swcPlugin(),
|
hermesSwcPlugin(),
|
||||||
hermesCPlugin({
|
hermesCPlugin({
|
||||||
flags: [
|
flags: [
|
||||||
dev ? '-Og' : '-O',
|
dev ? '-Og' : '-O',
|
||||||
|
|
@ -172,130 +143,6 @@ export default async function build(dev = Dev, log = true) {
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
function swcPlugin() {
|
|
||||||
return {
|
|
||||||
name: 'swc',
|
|
||||||
transform: {
|
|
||||||
filter: {
|
|
||||||
moduleType: ['js', 'jsx', 'ts', 'tsx'],
|
|
||||||
},
|
|
||||||
handler(code) {
|
|
||||||
return transform(code, {
|
|
||||||
jsc: {
|
|
||||||
transform: {
|
|
||||||
react: {
|
|
||||||
runtime: 'automatic',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
parser: {
|
|
||||||
syntax: 'typescript',
|
|
||||||
tsx: true,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
env: {
|
|
||||||
// https://github.com/facebook/hermes/blob/main/doc/Features.md
|
|
||||||
targets: 'fully supports es6',
|
|
||||||
include: [
|
|
||||||
'transform-async-generator-functions',
|
|
||||||
'transform-block-scoping',
|
|
||||||
'transform-classes',
|
|
||||||
'transform-duplicate-named-capturing-groups-regex',
|
|
||||||
'transform-named-capturing-groups-regex',
|
|
||||||
],
|
|
||||||
exclude: [
|
|
||||||
// Async functions are supported, only async arrow functions aren't
|
|
||||||
// Source: https://github.com/facebook/hermes/issues/1395
|
|
||||||
'transform-async-to-generator',
|
|
||||||
'transform-exponentiation-operator',
|
|
||||||
'transform-logical-assignment-operators',
|
|
||||||
'transform-nullish-coalescing-operator',
|
|
||||||
'transform-numeric-separator',
|
|
||||||
'transform-object-rest-spread',
|
|
||||||
'transform-optional-catch-binding',
|
|
||||||
'transform-optional-chaining',
|
|
||||||
'transform-parameters',
|
|
||||||
'transform-template-literals',
|
|
||||||
],
|
|
||||||
},
|
|
||||||
})
|
|
||||||
},
|
|
||||||
},
|
|
||||||
} satisfies RolldownPlugin
|
|
||||||
}
|
|
||||||
|
|
||||||
async function hermesCPlugin({
|
|
||||||
after,
|
|
||||||
before,
|
|
||||||
flags,
|
|
||||||
}: {
|
|
||||||
flags?: string[]
|
|
||||||
before?: (v: string) => void
|
|
||||||
after?: (v: string) => void
|
|
||||||
} = {}) {
|
|
||||||
const paths = {
|
|
||||||
win32: 'win64-bin/hermesc.exe',
|
|
||||||
darwin: 'osx-bin/hermesc',
|
|
||||||
linux: 'linux64-bin/hermesc',
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!(process.platform in paths))
|
|
||||||
throw new Error(`Unsupported platform: ${process.platform}`)
|
|
||||||
|
|
||||||
const sdksDir = './node_modules/react-native/sdks'
|
|
||||||
const binPath = `${sdksDir}/hermesc/${paths[process.platform as keyof typeof paths]}`
|
|
||||||
|
|
||||||
if (!existsSync(binPath))
|
|
||||||
throw new Error(
|
|
||||||
`Hermes compiler not found at ${binPath}. Please ensure you have react-native installed.`,
|
|
||||||
)
|
|
||||||
|
|
||||||
const ver = await Bun.file(`${sdksDir}/.hermesversion`).text()
|
|
||||||
|
|
||||||
return {
|
|
||||||
name: 'hermesc',
|
|
||||||
generateBundle(_, bundle) {
|
|
||||||
if (before) before(ver)
|
|
||||||
|
|
||||||
const file = bundle['revenge.js'] as OutputChunk
|
|
||||||
if (!file || !file.code) throw new Error('No code to compile')
|
|
||||||
|
|
||||||
// TODO(scripts/build): Remove this when we have a better way to add sourceURL
|
|
||||||
file.code += `//# sourceURL=Revenge`
|
|
||||||
|
|
||||||
const cmdlist = [binPath, '-emit-binary', ...(flags ?? [])]
|
|
||||||
|
|
||||||
const cmd = Bun.spawnSync<'pipe', 'pipe'>(cmdlist, {
|
|
||||||
// @ts-expect-error: Types are incorrect, but this works
|
|
||||||
stdin: new Blob([file.code]),
|
|
||||||
stdout: 'pipe',
|
|
||||||
})
|
|
||||||
|
|
||||||
if (cmd.exitCode) {
|
|
||||||
if (cmd.stderr.length)
|
|
||||||
throw new Error(
|
|
||||||
`Got error from hermesc: ${cmd.stderr.toString()}`,
|
|
||||||
)
|
|
||||||
else
|
|
||||||
throw new Error(`hermesc exited with code: ${cmd.exitCode}`)
|
|
||||||
}
|
|
||||||
|
|
||||||
const buf = cmd.stdout
|
|
||||||
if (!buf.length)
|
|
||||||
throw new Error(
|
|
||||||
`No output from hermesc. Probably a compilation error.\nTry running the command manually: ${cmdlist.join(' ')}`,
|
|
||||||
)
|
|
||||||
|
|
||||||
this.emitFile({
|
|
||||||
type: 'asset',
|
|
||||||
fileName: `${file.fileName.split('.')[0]!}.bundle`,
|
|
||||||
source: buf,
|
|
||||||
})
|
|
||||||
|
|
||||||
if (after) after(ver)
|
|
||||||
},
|
|
||||||
} satisfies RolldownPlugin
|
|
||||||
}
|
|
||||||
|
|
||||||
async function generateAssets() {
|
async function generateAssets() {
|
||||||
if (!(await exists(GeneratedAssetsDir)))
|
if (!(await exists(GeneratedAssetsDir)))
|
||||||
await mkdir(GeneratedAssetsDir, { recursive: true })
|
await mkdir(GeneratedAssetsDir, { recursive: true })
|
||||||
|
|
|
||||||
53
scripts/plugins/hermes-swc.ts
Normal file
53
scripts/plugins/hermes-swc.ts
Normal file
|
|
@ -0,0 +1,53 @@
|
||||||
|
import { transform } from '@swc/core'
|
||||||
|
import type { RolldownPlugin } from 'rolldown'
|
||||||
|
|
||||||
|
export default function hermesSwcPlugin(): RolldownPlugin {
|
||||||
|
return {
|
||||||
|
name: 'swc',
|
||||||
|
transform: {
|
||||||
|
filter: {
|
||||||
|
moduleType: ['js', 'jsx', 'ts', 'tsx'],
|
||||||
|
},
|
||||||
|
handler(code) {
|
||||||
|
return transform(code, {
|
||||||
|
jsc: {
|
||||||
|
transform: {
|
||||||
|
react: {
|
||||||
|
runtime: 'automatic',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
parser: {
|
||||||
|
syntax: 'typescript',
|
||||||
|
tsx: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
env: {
|
||||||
|
// https://github.com/facebook/hermes/blob/main/doc/Features.md
|
||||||
|
targets: 'fully supports es6',
|
||||||
|
include: [
|
||||||
|
'transform-async-generator-functions',
|
||||||
|
'transform-block-scoping',
|
||||||
|
'transform-classes',
|
||||||
|
'transform-duplicate-named-capturing-groups-regex',
|
||||||
|
'transform-named-capturing-groups-regex',
|
||||||
|
],
|
||||||
|
exclude: [
|
||||||
|
// Async functions are supported, only async arrow functions aren't
|
||||||
|
// Source: https://github.com/facebook/hermes/issues/1395
|
||||||
|
'transform-async-to-generator',
|
||||||
|
'transform-exponentiation-operator',
|
||||||
|
'transform-logical-assignment-operators',
|
||||||
|
'transform-nullish-coalescing-operator',
|
||||||
|
'transform-numeric-separator',
|
||||||
|
'transform-object-rest-spread',
|
||||||
|
'transform-optional-catch-binding',
|
||||||
|
'transform-optional-chaining',
|
||||||
|
'transform-parameters',
|
||||||
|
'transform-template-literals',
|
||||||
|
],
|
||||||
|
},
|
||||||
|
})
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
75
scripts/plugins/hermesc.ts
Normal file
75
scripts/plugins/hermesc.ts
Normal file
|
|
@ -0,0 +1,75 @@
|
||||||
|
import { existsSync, readFileSync } from 'fs'
|
||||||
|
import type { OutputChunk, RolldownPlugin } from 'rolldown'
|
||||||
|
|
||||||
|
export default function hermesCPlugin({
|
||||||
|
after,
|
||||||
|
before,
|
||||||
|
flags,
|
||||||
|
}: {
|
||||||
|
flags?: string[]
|
||||||
|
before?: (v: string) => void
|
||||||
|
after?: (v: string) => void
|
||||||
|
} = {}): RolldownPlugin {
|
||||||
|
const paths = {
|
||||||
|
win32: 'win64-bin/hermesc.exe',
|
||||||
|
darwin: 'osx-bin/hermesc',
|
||||||
|
linux: 'linux64-bin/hermesc',
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!(process.platform in paths))
|
||||||
|
throw new Error(`Unsupported platform: ${process.platform}`)
|
||||||
|
|
||||||
|
const sdksDir = './node_modules/react-native/sdks'
|
||||||
|
const binPath = `${sdksDir}/hermesc/${paths[process.platform as keyof typeof paths]}`
|
||||||
|
|
||||||
|
if (!existsSync(binPath))
|
||||||
|
throw new Error(
|
||||||
|
`Hermes compiler not found at ${binPath}. Please ensure you have react-native installed.`,
|
||||||
|
)
|
||||||
|
|
||||||
|
const ver = readFileSync(`${sdksDir}/.hermesversion`).toString()
|
||||||
|
|
||||||
|
return {
|
||||||
|
name: 'hermesc',
|
||||||
|
generateBundle(_, bundle) {
|
||||||
|
if (before) before(ver)
|
||||||
|
|
||||||
|
const file = bundle['revenge.js'] as OutputChunk
|
||||||
|
if (!file || !file.code) throw new Error('No code to compile')
|
||||||
|
|
||||||
|
// TODO(scripts/build): Remove this when we have a better way to add sourceURL
|
||||||
|
file.code += `//# sourceURL=Revenge`
|
||||||
|
|
||||||
|
const cmdlist = [binPath, '-emit-binary', ...(flags ?? [])]
|
||||||
|
|
||||||
|
const cmd = Bun.spawnSync<'pipe', 'pipe'>(cmdlist, {
|
||||||
|
// @ts-expect-error: Types are incorrect, but this works
|
||||||
|
stdin: new Blob([file.code]),
|
||||||
|
stdout: 'pipe',
|
||||||
|
})
|
||||||
|
|
||||||
|
if (cmd.exitCode) {
|
||||||
|
if (cmd.stderr.length)
|
||||||
|
throw new Error(
|
||||||
|
`Got error from hermesc: ${cmd.stderr.toString()}`,
|
||||||
|
)
|
||||||
|
else
|
||||||
|
throw new Error(`hermesc exited with code: ${cmd.exitCode}`)
|
||||||
|
}
|
||||||
|
|
||||||
|
const buf = cmd.stdout
|
||||||
|
if (!buf.length)
|
||||||
|
throw new Error(
|
||||||
|
`No output from hermesc. Probably a compilation error.\nTry running the command manually: ${cmdlist.join(' ')}`,
|
||||||
|
)
|
||||||
|
|
||||||
|
this.emitFile({
|
||||||
|
type: 'asset',
|
||||||
|
fileName: `${file.fileName.split('.')[0]!}.bundle`,
|
||||||
|
source: buf,
|
||||||
|
})
|
||||||
|
|
||||||
|
if (after) after(ver)
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
35
scripts/plugins/shim-aliases.ts
Normal file
35
scripts/plugins/shim-aliases.ts
Normal file
|
|
@ -0,0 +1,35 @@
|
||||||
|
import { aliasPlugin } from 'rolldown/experimental'
|
||||||
|
import type { RolldownPlugin } from 'rolldown'
|
||||||
|
|
||||||
|
export default function shimAliases(dir: string): RolldownPlugin {
|
||||||
|
return aliasPlugin({
|
||||||
|
entries: [
|
||||||
|
{
|
||||||
|
find: 'react/jsx-runtime',
|
||||||
|
replacement: `${dir}/react~jsx-runtime.ts`,
|
||||||
|
},
|
||||||
|
// Do not move React to the top!
|
||||||
|
// If you do that, react/jsx-runtime would resolve to ${ShimsDir}/react.ts/jsx-runtime instead.
|
||||||
|
{
|
||||||
|
find: 'react',
|
||||||
|
replacement: `${dir}/react.ts`,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
find: 'react-native',
|
||||||
|
replacement: `${dir}/react-native.ts`,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
find: '@react-navigation/native',
|
||||||
|
replacement: `${dir}/@react-navigation~native.ts`,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
find: '@react-navigation/stack',
|
||||||
|
replacement: `${dir}/@react-navigation~stack.ts`,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
find: '@shopify/flash-list',
|
||||||
|
replacement: `${dir}/@shopify~flash-list.ts`,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
})
|
||||||
|
}
|
||||||
Loading…
Add table
Reference in a new issue