|
| 1 | +/* eslint-disable no-console -- output */ |
| 2 | +import { mkdir, readFile, rm, writeFile } from 'node:fs/promises'; |
| 3 | +import { dirname, join } from 'node:path'; |
| 4 | +import { fileURLToPath } from 'node:url'; |
| 5 | +import { build } from 'rolldown'; |
| 6 | +import { transform } from '@swc/core'; |
| 7 | +import compat from '@core-js/compat/compat.js'; |
| 8 | +import banner from './config.mjs'; |
| 9 | + |
| 10 | +function normalizeSummary(unit = {}) { |
| 11 | + let size, modules; |
| 12 | + if (typeof unit != 'object') { |
| 13 | + size = modules = !!unit; |
| 14 | + } else { |
| 15 | + size = !!unit.size; |
| 16 | + modules = !!unit.modules; |
| 17 | + } return { size, modules }; |
| 18 | +} |
| 19 | + |
| 20 | +function importIt(it) { |
| 21 | + return `import 'core-js/modules/${ it }.js';\n`; |
| 22 | +} |
| 23 | + |
| 24 | +function requireIt(it) { |
| 25 | + return `require('core-js/modules/${ it }');\n`; |
| 26 | +} |
| 27 | + |
| 28 | +function importModules(modules, format = 'esm') { |
| 29 | + return modules.map(format === 'esm' ? importIt : requireIt).join(''); |
| 30 | +} |
| 31 | + |
| 32 | +export default async function ({ |
| 33 | + modules = null, |
| 34 | + exclude = [], |
| 35 | + targets = null, |
| 36 | + format = 'bundle', |
| 37 | + filename = null, |
| 38 | + summary = {}, |
| 39 | +} = {}) { |
| 40 | + if (!['bundle', 'cjs', 'esm'].includes(format)) throw new TypeError('Incorrect output type'); |
| 41 | + summary = { comment: normalizeSummary(summary.comment), console: normalizeSummary(summary.console) }; |
| 42 | + |
| 43 | + const TITLE = filename !== null || filename !== undefined ? filename : '`core-js`'; |
| 44 | + let script = banner; |
| 45 | + let code = '\n'; |
| 46 | + |
| 47 | + const { list, targets: compatTargets } = compat({ targets, modules, exclude }); |
| 48 | + |
| 49 | + if (list.length) { |
| 50 | + if (format === 'bundle') { |
| 51 | + const tempDir = join(dirname(fileURLToPath(import.meta.url)), '__tmp__'); |
| 52 | + const tempFile = join(tempDir, `core-js-${ Math.random().toString(36).slice(2) }.js`); |
| 53 | + const templateFile = `${ tempFile }-template.js`; |
| 54 | + |
| 55 | + try { |
| 56 | + await mkdir(tempDir, { recursive: true }); |
| 57 | + await writeFile(templateFile, importModules(list)); |
| 58 | + console.time(1); |
| 59 | + await build({ |
| 60 | + input: templateFile, |
| 61 | + platform: 'neutral', |
| 62 | + treeshake: false, |
| 63 | + output: { |
| 64 | + externalLiveBindings: false, |
| 65 | + format: 'iife', |
| 66 | + file: tempFile, |
| 67 | + keepNames: true, |
| 68 | + minifyInternalExports: true, |
| 69 | + }, |
| 70 | + }); |
| 71 | + console.timeEnd(1); |
| 72 | + code = String(await readFile(tempFile, 'utf8')); |
| 73 | + } finally { |
| 74 | + await rm(templateFile, { force: true }); |
| 75 | + await rm(tempFile, { force: true }); |
| 76 | + } |
| 77 | + |
| 78 | + // rolldown helpers / wrappers contain arrows |
| 79 | + code = (await transform(code, { |
| 80 | + env: { |
| 81 | + include: [ |
| 82 | + 'transform-arrow-functions', |
| 83 | + 'transform-shorthand-properties', |
| 84 | + ], |
| 85 | + }, |
| 86 | + })).code; |
| 87 | + |
| 88 | + code = `!function (undefined) { 'use strict'; ${ code } }();\n`; |
| 89 | + } else { |
| 90 | + code = importModules(list, format); |
| 91 | + } |
| 92 | + } |
| 93 | + |
| 94 | + if (summary.comment.size) script += `/*\n * size: ${ (code.length / 1024).toFixed(2) }KB w/o comments\n */`; |
| 95 | + if (summary.comment.modules) script += `/*\n * modules:\n${ list.map(it => ` * ${ it }\n`).join('') } */`; |
| 96 | + if (code) script += `\n${ code }`; |
| 97 | + |
| 98 | + if (summary.console.size) { |
| 99 | + console.log(`\u001B[32mbundling \u001B[36m${ TITLE }\u001B[32m, size: \u001B[36m${ |
| 100 | + (script.length / 1024).toFixed(2) |
| 101 | + }KB\u001B[0m`); |
| 102 | + } |
| 103 | + |
| 104 | + if (summary.console.modules) { |
| 105 | + console.log(`\u001B[32mbundling \u001B[36m${ TITLE }\u001B[32m, modules:\u001B[0m`); |
| 106 | + if (list.length) for (const it of list) { |
| 107 | + console.log(`\u001B[36m${ it + (targets ? ` \u001B[32mfor \u001B[36m${ JSON.stringify(compatTargets[it]) }` : '') }\u001B[0m`); |
| 108 | + } else console.log('\u001B[36mnothing\u001B[0m'); |
| 109 | + } |
| 110 | + |
| 111 | + if (!(filename === null || filename === undefined)) { |
| 112 | + await mkdir(dirname(filename), { recursive: true }); |
| 113 | + await writeFile(filename, script); |
| 114 | + } |
| 115 | + |
| 116 | + return { script }; |
| 117 | +} |
0 commit comments