buildPackage.js 3.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124
  1. const path = require("path");
  2. const fs = require("fs");
  3. const { pathToFileURL } = require("url");
  4. const { build } = require("esbuild");
  5. const { sassPlugin } = require("esbuild-sass-plugin");
  6. const { parseEnvVariables } = require("../packages/excalidraw/env.cjs");
  7. const ENV_VARS = {
  8. development: {
  9. ...parseEnvVariables(`${__dirname}/../.env.development`),
  10. DEV: true,
  11. },
  12. production: {
  13. ...parseEnvVariables(`${__dirname}/../.env.production`),
  14. PROD: true,
  15. },
  16. };
  17. // Resolve a relative path from the source file's directory
  18. const resolveRelativePath = (importPath, sourceFile) => {
  19. const sourceDir = path.dirname(sourceFile);
  20. const extensions = [".scss", ".css", ""];
  21. for (const ext of extensions) {
  22. const fullPath = path.resolve(sourceDir, importPath + ext);
  23. if (fs.existsSync(fullPath)) {
  24. return fullPath;
  25. }
  26. // Try with underscore prefix for partials
  27. const partialPath = path.join(
  28. path.dirname(fullPath),
  29. `_${path.basename(fullPath)}`,
  30. );
  31. if (fs.existsSync(partialPath)) {
  32. return partialPath;
  33. }
  34. }
  35. return null;
  36. };
  37. // Precompile function to convert relative paths to absolute paths
  38. const precompile = (source, sourcePath) => {
  39. // Match @use and @forward statements with relative paths
  40. const importRegex = /(@use|@forward)\s+["'](\.[^"']+)["']/g;
  41. return source.replace(importRegex, (match, directive, importPath) => {
  42. const resolvedPath = resolveRelativePath(importPath, sourcePath);
  43. if (resolvedPath) {
  44. // Convert to file:// URL format for sass
  45. const fileUrl = pathToFileURL(resolvedPath).href;
  46. return `${directive} "${fileUrl}"`;
  47. }
  48. return match;
  49. });
  50. };
  51. // excludes all external dependencies and bundles only the source code
  52. const getConfig = (outdir) => ({
  53. outdir,
  54. bundle: true,
  55. splitting: true,
  56. format: "esm",
  57. packages: "external",
  58. plugins: [
  59. sassPlugin({
  60. precompile,
  61. }),
  62. ],
  63. target: "es2020",
  64. assetNames: "[dir]/[name]",
  65. chunkNames: "[dir]/[name]-[hash]",
  66. alias: {
  67. "@excalidraw/utils": path.resolve(__dirname, "../packages/utils/src"),
  68. },
  69. external: ["@excalidraw/common", "@excalidraw/element", "@excalidraw/math"],
  70. loader: {
  71. ".woff2": "file",
  72. },
  73. });
  74. function buildDev(config) {
  75. return build({
  76. ...config,
  77. sourcemap: true,
  78. define: {
  79. "import.meta.env": JSON.stringify(ENV_VARS.development),
  80. },
  81. });
  82. }
  83. function buildProd(config) {
  84. return build({
  85. ...config,
  86. minify: true,
  87. define: {
  88. "import.meta.env": JSON.stringify(ENV_VARS.production),
  89. },
  90. });
  91. }
  92. const createESMRawBuild = async () => {
  93. const chunksConfig = {
  94. entryPoints: ["index.tsx", "**/*.chunk.ts"],
  95. entryNames: "[name]",
  96. };
  97. // development unminified build with source maps
  98. await buildDev({
  99. ...getConfig("dist/dev"),
  100. ...chunksConfig,
  101. });
  102. // production minified buld without sourcemaps
  103. await buildProd({
  104. ...getConfig("dist/prod"),
  105. ...chunksConfig,
  106. });
  107. };
  108. (async () => {
  109. await createESMRawBuild();
  110. })();