build.js 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140
  1. import { deleteAsync } from 'del';
  2. import esbuild from 'esbuild';
  3. import { copy } from 'esbuild-plugin-copy';
  4. import { dim, green, red, yellow } from 'kleur/colors';
  5. import { promises as fs } from 'node:fs';
  6. import glob from 'tiny-glob';
  7. import svelte from '../utils/svelte-plugin.js';
  8. import prebuild from './prebuild.js';
  9. /** @type {import('esbuild').BuildOptions} */
  10. const defaultConfig = {
  11. minify: false,
  12. format: 'esm',
  13. platform: 'node',
  14. target: 'node18',
  15. sourcemap: false,
  16. sourcesContent: false,
  17. };
  18. const dt = new Intl.DateTimeFormat('en-us', {
  19. hour: '2-digit',
  20. minute: '2-digit',
  21. });
  22. function getPrebuilds(isDev, args) {
  23. let prebuilds = [];
  24. while (args.includes('--prebuild')) {
  25. let idx = args.indexOf('--prebuild');
  26. prebuilds.push(args[idx + 1]);
  27. args.splice(idx, 2);
  28. }
  29. if (prebuilds.length && isDev) {
  30. prebuilds.unshift('--no-minify');
  31. }
  32. return prebuilds;
  33. }
  34. export default async function build(...args) {
  35. const config = Object.assign({}, defaultConfig);
  36. const isDev = args.slice(-1)[0] === 'IS_DEV';
  37. const prebuilds = getPrebuilds(isDev, args);
  38. const patterns = args
  39. .filter((f) => !!f) // remove empty args
  40. .map((f) => f.replace(/^'/, '').replace(/'$/, '')); // Needed for Windows: glob strings contain surrounding string chars??? remove these
  41. let entryPoints = [].concat(
  42. ...(await Promise.all(
  43. patterns.map((pattern) => glob(pattern, { filesOnly: true, absolute: true }))
  44. ))
  45. );
  46. const noClean = args.includes('--no-clean-dist');
  47. const bundle = args.includes('--bundle');
  48. const forceCJS = args.includes('--force-cjs');
  49. const copyWASM = args.includes('--copy-wasm');
  50. const {
  51. type = 'module',
  52. version,
  53. dependencies = {},
  54. } = await fs.readFile('./package.json').then((res) => JSON.parse(res.toString()));
  55. // expose PACKAGE_VERSION on process.env for CLI utils
  56. config.define = { 'process.env.PACKAGE_VERSION': JSON.stringify(version) };
  57. const format = type === 'module' && !forceCJS ? 'esm' : 'cjs';
  58. const outdir = 'dist';
  59. if (!noClean) {
  60. await clean(outdir);
  61. }
  62. if (!isDev) {
  63. await esbuild.build({
  64. ...config,
  65. bundle,
  66. external: bundle ? Object.keys(dependencies) : undefined,
  67. entryPoints,
  68. outdir,
  69. outExtension: forceCJS ? { '.js': '.cjs' } : {},
  70. format,
  71. });
  72. return;
  73. }
  74. const rebuildPlugin = {
  75. name: 'astro:rebuild',
  76. setup(build) {
  77. build.onEnd(async (result) => {
  78. if (prebuilds.length) {
  79. await prebuild(...prebuilds);
  80. }
  81. const date = dt.format(new Date());
  82. if (result && result.errors.length) {
  83. console.error(dim(`[${date}] `) + red(error || result.errors.join('\n')));
  84. } else {
  85. if (result.warnings.length) {
  86. console.log(
  87. dim(`[${date}] `) + yellow('⚠ updated with warnings:\n' + result.warnings.join('\n'))
  88. );
  89. }
  90. console.log(dim(`[${date}] `) + green('✔ updated'));
  91. }
  92. });
  93. },
  94. };
  95. const builder = await esbuild.context({
  96. ...config,
  97. entryPoints,
  98. outdir,
  99. format,
  100. sourcemap: 'linked',
  101. plugins: [
  102. rebuildPlugin,
  103. svelte({ isDev }),
  104. ...(copyWASM
  105. ? [
  106. copy({
  107. resolveFrom: 'cwd',
  108. assets: {
  109. from: ['./src/assets/services/vendor/squoosh/**/*.wasm'],
  110. to: ['./dist/assets/services/vendor/squoosh'],
  111. },
  112. }),
  113. ]
  114. : []),
  115. ],
  116. });
  117. await builder.watch();
  118. process.on('beforeExit', () => {
  119. builder.stop && builder.stop();
  120. });
  121. }
  122. async function clean(outdir) {
  123. await deleteAsync([`${outdir}/**`, `!${outdir}/**/*.d.ts`], {
  124. onlyFiles: true,
  125. });
  126. }