@shopify/cli-hydrogen 8.0.3 → 8.0.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,38 +1,35 @@
1
1
  import { Flags } from '@oclif/core';
2
2
  import Command from '@shopify/cli-kit/node/base-command';
3
- import { outputInfo, outputContent, outputToken, outputWarn } from '@shopify/cli-kit/node/output';
4
- import { rmdir, fileSize, glob, readFile, writeFile, fileExists, copyFile } from '@shopify/cli-kit/node/fs';
5
- import { resolvePath, relativePath, joinPath } from '@shopify/cli-kit/node/path';
3
+ import { resolvePath, joinPath } from '@shopify/cli-kit/node/path';
4
+ import { collectLog, outputWarn } from '@shopify/cli-kit/node/output';
5
+ import { removeFile, fileSize } from '@shopify/cli-kit/node/fs';
6
6
  import { getPackageManager } from '@shopify/cli-kit/node/node-package-manager';
7
- import colors from '@shopify/cli-kit/node/colors';
8
- import { getProjectPaths, getRemixConfig, handleRemixImportFail, assertOxygenChecks } from '../../lib/remix-config.js';
9
7
  import { commonFlags, flagsToCamelObject } from '../../lib/flags.js';
8
+ import { prepareDiffDirectory, copyDiffBuild } from '../../lib/template-diff.js';
9
+ import { hasViteConfig, getViteConfig } from '../../lib/vite-config.js';
10
10
  import { checkLockfileStatus } from '../../lib/check-lockfile.js';
11
11
  import { findMissingRoutes } from '../../lib/missing-routes.js';
12
- import { muteRemixLogs, createRemixLogger } from '../../lib/log.js';
12
+ import { runClassicCompilerBuild } from '../../lib/classic-compiler/build.js';
13
13
  import { codegen } from '../../lib/codegen.js';
14
- import { buildBundleAnalysis, getBundleAnalysisSummary } from '../../lib/bundle/analyzer.js';
15
14
  import { isCI } from '../../lib/is-ci.js';
16
- import { prepareDiffDirectory, copyDiffBuild } from '../../lib/template-diff.js';
17
- import { hasViteConfig } from '../../lib/vite-config.js';
18
15
 
19
- const LOG_WORKER_BUILT = "\u{1F4E6} Worker built";
20
- const WORKER_BUILD_SIZE_LIMIT = 5;
21
16
  class Build extends Command {
22
17
  static descriptionWithMarkdown = `Builds a Hydrogen storefront for production. The client and app worker files are compiled to a \`/dist\` folder in your Hydrogen project directory.`;
23
18
  static description = "Builds a Hydrogen storefront for production.";
24
19
  static flags = {
25
20
  ...commonFlags.path,
21
+ ...commonFlags.entry,
26
22
  ...commonFlags.sourcemap,
27
- "bundle-stats": Flags.boolean({
28
- description: "Show a bundle size summary after building. Defaults to true, use `--no-bundle-stats` to disable.",
29
- default: true,
30
- allowNo: true
31
- }),
32
23
  ...commonFlags.lockfileCheck,
33
24
  ...commonFlags.disableRouteWarning,
34
25
  ...commonFlags.codegen,
35
- ...commonFlags.diff
26
+ ...commonFlags.diff,
27
+ // For the classic compiler:
28
+ "bundle-stats": Flags.boolean({
29
+ description: "[Classic Remix Compiler] Show a bundle size summary after building. Defaults to true, use `--no-bundle-stats` to disable.",
30
+ default: true,
31
+ allowNo: true
32
+ })
36
33
  };
37
34
  async run() {
38
35
  const { flags } = await this.parse(Build);
@@ -46,11 +43,10 @@ class Build extends Command {
46
43
  useCodegen: flags.codegen,
47
44
  directory
48
45
  };
49
- if (await hasViteConfig(directory ?? process.cwd())) {
50
- const { runViteBuild } = await import('./build-vite.js');
51
- await runViteBuild(buildParams);
52
- } else {
46
+ if (await hasViteConfig(directory)) {
53
47
  await runBuild(buildParams);
48
+ } else {
49
+ await runClassicCompilerBuild(buildParams);
54
50
  }
55
51
  if (flags.diff) {
56
52
  await copyDiffBuild(directory, originalDirectory);
@@ -58,81 +54,83 @@ class Build extends Command {
58
54
  process.exit(0);
59
55
  }
60
56
  }
57
+ const WORKER_BUILD_SIZE_LIMIT = 5;
61
58
  async function runBuild({
59
+ entry: ssrEntry,
62
60
  directory,
63
61
  useCodegen = false,
64
62
  codegenConfigPath,
65
63
  sourcemap = false,
66
64
  disableRouteWarning = false,
67
- bundleStats = true,
68
65
  lockfileCheck = true,
69
- assetPath
66
+ assetPath = "/"
70
67
  }) {
71
68
  if (!process.env.NODE_ENV) {
72
69
  process.env.NODE_ENV = "production";
73
70
  }
74
- if (assetPath) {
75
- process.env.HYDROGEN_ASSET_BASE_URL = assetPath;
76
- }
77
- const { root, buildPath, buildPathClient, buildPathWorkerFile, publicPath } = getProjectPaths(directory);
71
+ const root = directory ?? process.cwd();
78
72
  if (lockfileCheck) {
79
73
  await checkLockfileStatus(root, isCI());
80
74
  }
81
- await muteRemixLogs();
82
- console.time(LOG_WORKER_BUILT);
83
- outputInfo(`
84
- \u{1F3D7}\uFE0F Building in ${process.env.NODE_ENV} mode...`);
85
- const [remixConfig, [{ build }, { logThrown }, { createFileWatchCache }]] = await Promise.all([
86
- getRemixConfig(root),
87
- Promise.all([
88
- import('@remix-run/dev/dist/compiler/build.js'),
89
- import('@remix-run/dev/dist/compiler/utils/log.js'),
90
- import('@remix-run/dev/dist/compiler/fileWatchCache.js')
91
- ]).catch(handleRemixImportFail),
92
- rmdir(buildPath, { force: true })
75
+ const [
76
+ vite,
77
+ { userViteConfig, remixConfig, clientOutDir, serverOutDir, serverOutFile }
78
+ ] = await Promise.all([
79
+ // Avoid static imports because this file is imported by `deploy` command,
80
+ // which must have a hard dependency on 'vite'.
81
+ import('vite'),
82
+ getViteConfig(root, ssrEntry)
93
83
  ]);
94
- assertOxygenChecks(remixConfig);
84
+ const customLogger = vite.createLogger();
85
+ if (process.env.SHOPIFY_UNIT_TEST) {
86
+ customLogger.info = (msg) => collectLog("info", msg);
87
+ customLogger.warn = (msg) => collectLog("warn", msg);
88
+ customLogger.error = (msg) => collectLog("error", msg);
89
+ }
90
+ const serverMinify = userViteConfig.build?.minify ?? true;
91
+ const commonConfig = {
92
+ root,
93
+ mode: process.env.NODE_ENV,
94
+ base: assetPath,
95
+ customLogger
96
+ };
97
+ await vite.build({
98
+ ...commonConfig,
99
+ build: {
100
+ emptyOutDir: true,
101
+ copyPublicDir: true,
102
+ // Disable client sourcemaps in production
103
+ sourcemap: process.env.NODE_ENV !== "production" && sourcemap
104
+ }
105
+ });
106
+ console.log("");
107
+ await vite.build({
108
+ ...commonConfig,
109
+ build: {
110
+ sourcemap,
111
+ ssr: ssrEntry ?? true,
112
+ emptyOutDir: false,
113
+ copyPublicDir: false,
114
+ minify: serverMinify
115
+ }
116
+ });
95
117
  await Promise.all([
96
- copyPublicFiles(publicPath, buildPathClient),
97
- build({
98
- config: remixConfig,
99
- options: {
100
- mode: process.env.NODE_ENV,
101
- sourcemap
102
- },
103
- logger: createRemixLogger(),
104
- fileWatchCache: createFileWatchCache()
105
- }).catch((thrown) => {
106
- logThrown(thrown);
107
- if (process.env.SHOPIFY_UNIT_TEST) {
108
- throw thrown;
109
- } else {
110
- process.exit(1);
111
- }
112
- }),
113
- useCodegen && codegen({ ...remixConfig, configFilePath: codegenConfigPath })
118
+ removeFile(joinPath(clientOutDir, ".vite")),
119
+ removeFile(joinPath(serverOutDir, ".vite")),
120
+ removeFile(joinPath(serverOutDir, "assets"))
114
121
  ]);
122
+ if (useCodegen) {
123
+ await codegen({
124
+ rootDirectory: root,
125
+ appDirectory: remixConfig.appDirectory,
126
+ configFilePath: codegenConfigPath
127
+ });
128
+ }
115
129
  if (process.env.NODE_ENV !== "development") {
116
- console.timeEnd(LOG_WORKER_BUILT);
117
- const bundleAnalysisPath = await buildBundleAnalysis(buildPath);
118
- const sizeMB = await fileSize(buildPathWorkerFile) / (1024 * 1024);
119
- const formattedSize = colors.yellow(sizeMB.toFixed(2) + " MB");
120
- outputInfo(
121
- outputContent` ${colors.dim(
122
- relativePath(root, buildPathWorkerFile)
123
- )} ${bundleAnalysisPath ? outputToken.link(formattedSize, bundleAnalysisPath) : formattedSize}\n`
124
- );
125
- if (bundleStats && bundleAnalysisPath) {
126
- outputInfo(
127
- outputContent`${await getBundleAnalysisSummary(buildPathWorkerFile) || "\n"}\n │\n └─── ${outputToken.link(
128
- "Complete analysis: " + bundleAnalysisPath,
129
- bundleAnalysisPath
130
- )}\n\n`
131
- );
132
- }
130
+ const sizeMB = await fileSize(serverOutFile) / (1024 * 1024);
133
131
  if (sizeMB >= WORKER_BUILD_SIZE_LIMIT) {
134
132
  outputWarn(
135
- `\u{1F6A8} Smaller worker bundles are faster to deploy and run.${remixConfig.serverMinify ? "" : "\n Minify your bundle by adding `serverMinify: true` to remix.config.js."}
133
+ `\u{1F6A8} Smaller worker bundles are faster to deploy and run.${serverMinify ? "" : "\n Minify your bundle by adding `build.minify: true` to vite.config.js."}
136
134
  Learn more about optimizing your worker bundle file: https://h2o.fyi/debugging/bundle-size
137
135
  `
138
136
  );
@@ -151,27 +149,6 @@ This build is missing ${missingRoutes.length} route${missingRoutes.length > 1 ?
151
149
  );
152
150
  }
153
151
  }
154
- if (process.env.NODE_ENV !== "development") {
155
- await cleanClientSourcemaps(buildPathClient);
156
- }
157
- }
158
- async function cleanClientSourcemaps(buildPathClient) {
159
- const bundleFiles = await glob(joinPath(buildPathClient, "**/*.js"));
160
- await Promise.all(
161
- bundleFiles.map(async (filePath) => {
162
- const file = await readFile(filePath);
163
- return await writeFile(
164
- filePath,
165
- file.replace(/\/\/# sourceMappingURL=.+\.js\.map$/gm, "")
166
- );
167
- })
168
- );
169
- }
170
- async function copyPublicFiles(publicPath, buildPathClient) {
171
- if (!await fileExists(publicPath)) {
172
- return;
173
- }
174
- return copyFile(publicPath, buildPathClient);
175
152
  }
176
153
 
177
- export { copyPublicFiles, Build as default, runBuild };
154
+ export { Build as default, runBuild };
@@ -14,8 +14,8 @@ import { findEnvironmentOrThrow, findEnvironmentByBranchOrThrow, orderEnvironmen
14
14
  import { execAsync } from '../../lib/process.js';
15
15
  import { commonFlags, flagsToCamelObject } from '../../lib/flags.js';
16
16
  import { getOxygenDeploymentData } from '../../lib/get-oxygen-deployment-data.js';
17
+ import { runClassicCompilerBuild } from '../../lib/classic-compiler/build.js';
17
18
  import { runBuild } from './build.js';
18
- import { runViteBuild } from './build-vite.js';
19
19
  import { getViteConfig } from '../../lib/vite-config.js';
20
20
  import { prepareDiffDirectory } from '../../lib/template-diff.js';
21
21
  import { hasRemixConfigFile } from '../../lib/remix-config.js';
@@ -425,7 +425,7 @@ Continue?`.value
425
425
  outputInfo(
426
426
  outputContent`${colors.whiteBright("Building project...")}`.value
427
427
  );
428
- const build = isClassicCompiler ? runBuild : runViteBuild;
428
+ const build = isClassicCompiler ? runClassicCompilerBuild : runBuild;
429
429
  await build({
430
430
  directory: root,
431
431
  assetPath,