@nx/next 0.0.0-pr-22179-271588f

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.
Files changed (158) hide show
  1. package/LICENSE +22 -0
  2. package/README.md +68 -0
  3. package/babel.d.ts +0 -0
  4. package/babel.js +12 -0
  5. package/executors.json +20 -0
  6. package/generators.json +47 -0
  7. package/index.d.ts +8 -0
  8. package/index.js +19 -0
  9. package/migrations.json +106 -0
  10. package/package.json +60 -0
  11. package/plugin.d.ts +1 -0
  12. package/plugin.js +5 -0
  13. package/plugins/component-testing.d.ts +2 -0
  14. package/plugins/component-testing.js +96 -0
  15. package/plugins/with-less.d.ts +3 -0
  16. package/plugins/with-less.js +79 -0
  17. package/plugins/with-nx.d.ts +25 -0
  18. package/plugins/with-nx.js +297 -0
  19. package/plugins/with-stylus.d.ts +3 -0
  20. package/plugins/with-stylus.js +12 -0
  21. package/src/executors/build/build.impl.d.ts +5 -0
  22. package/src/executors/build/build.impl.js +106 -0
  23. package/src/executors/build/lib/check-project.d.ts +1 -0
  24. package/src/executors/build/lib/check-project.js +12 -0
  25. package/src/executors/build/lib/create-next-config-file.d.ts +14 -0
  26. package/src/executors/build/lib/create-next-config-file.js +162 -0
  27. package/src/executors/build/lib/test-fixtures/ensure-exts/baz.json +1 -0
  28. package/src/executors/build/lib/update-package-json.d.ts +3 -0
  29. package/src/executors/build/lib/update-package-json.js +30 -0
  30. package/src/executors/build/schema.json +76 -0
  31. package/src/executors/export/export.impl.d.ts +17 -0
  32. package/src/executors/export/export.impl.js +58 -0
  33. package/src/executors/export/schema.json +30 -0
  34. package/src/executors/server/custom-server.impl.d.ts +6 -0
  35. package/src/executors/server/custom-server.impl.js +36 -0
  36. package/src/executors/server/schema.json +63 -0
  37. package/src/executors/server/server.impl.d.ts +6 -0
  38. package/src/executors/server/server.impl.js +66 -0
  39. package/src/generators/application/application.d.ts +4 -0
  40. package/src/generators/application/application.js +85 -0
  41. package/src/generators/application/files/app/api/hello/route.ts__tmpl__ +4 -0
  42. package/src/generators/application/files/app/global.__stylesExt____tmpl__ +1 -0
  43. package/src/generators/application/files/app/page.module.__style__ +1 -0
  44. package/src/generators/application/files/app/page.tsx__tmpl__ +30 -0
  45. package/src/generators/application/files/app-default-layout/layout.tsx__tmpl__ +18 -0
  46. package/src/generators/application/files/app-styled-components/layout.tsx__tmpl__ +21 -0
  47. package/src/generators/application/files/app-styled-components/registry.tsx__tmpl__ +33 -0
  48. package/src/generators/application/files/app-styled-jsx/layout.tsx__tmpl__ +16 -0
  49. package/src/generators/application/files/app-styled-jsx/registry.tsx__tmpl__ +23 -0
  50. package/src/generators/application/files/common/__dot__babelrc +21 -0
  51. package/src/generators/application/files/common/index.d.ts__tmpl__ +13 -0
  52. package/src/generators/application/files/common/next-env.d.ts__tmpl__ +5 -0
  53. package/src/generators/application/files/common/next.config.js__tmpl__ +82 -0
  54. package/src/generators/application/files/common/public/.gitkeep +0 -0
  55. package/src/generators/application/files/common/public/favicon.ico +0 -0
  56. package/src/generators/application/files/common/specs/__fileName__.spec.tsx__tmpl__ +18 -0
  57. package/src/generators/application/files/common/tsconfig.json__tmpl__ +29 -0
  58. package/src/generators/application/files/pages/__fileName__.module.__style__ +1 -0
  59. package/src/generators/application/files/pages/__fileName__.tsx__tmpl__ +30 -0
  60. package/src/generators/application/files/pages/_app.tsx__tmpl__ +18 -0
  61. package/src/generators/application/files/pages/_document.tsx__tmpl__ +33 -0
  62. package/src/generators/application/files/pages/styles.__stylesExt____tmpl__ +1 -0
  63. package/src/generators/application/lib/add-e2e.d.ts +3 -0
  64. package/src/generators/application/lib/add-e2e.js +72 -0
  65. package/src/generators/application/lib/add-jest.d.ts +3 -0
  66. package/src/generators/application/lib/add-jest.js +38 -0
  67. package/src/generators/application/lib/add-linting.d.ts +3 -0
  68. package/src/generators/application/lib/add-linting.js +62 -0
  69. package/src/generators/application/lib/add-plugin.d.ts +2 -0
  70. package/src/generators/application/lib/add-plugin.js +25 -0
  71. package/src/generators/application/lib/add-project.d.ts +3 -0
  72. package/src/generators/application/lib/add-project.js +66 -0
  73. package/src/generators/application/lib/create-application-files.d.ts +3 -0
  74. package/src/generators/application/lib/create-application-files.helpers.d.ts +2 -0
  75. package/src/generators/application/lib/create-application-files.helpers.js +846 -0
  76. package/src/generators/application/lib/create-application-files.js +114 -0
  77. package/src/generators/application/lib/normalize-options.d.ts +14 -0
  78. package/src/generators/application/lib/normalize-options.js +56 -0
  79. package/src/generators/application/lib/set-defaults.d.ts +3 -0
  80. package/src/generators/application/lib/set-defaults.js +14 -0
  81. package/src/generators/application/lib/show-possible-warnings.d.ts +3 -0
  82. package/src/generators/application/lib/show-possible-warnings.js +10 -0
  83. package/src/generators/application/lib/update-cypress-tsconfig.d.ts +3 -0
  84. package/src/generators/application/lib/update-cypress-tsconfig.js +16 -0
  85. package/src/generators/application/lib/update-jest-config.d.ts +3 -0
  86. package/src/generators/application/lib/update-jest-config.js +15 -0
  87. package/src/generators/application/schema.d.ts +24 -0
  88. package/src/generators/application/schema.json +146 -0
  89. package/src/generators/component/component.d.ts +28 -0
  90. package/src/generators/component/component.js +66 -0
  91. package/src/generators/component/schema.json +125 -0
  92. package/src/generators/custom-server/custom-server.d.ts +3 -0
  93. package/src/generators/custom-server/custom-server.js +104 -0
  94. package/src/generators/custom-server/files/server/main.ts__tmpl__ +46 -0
  95. package/src/generators/custom-server/files/tsconfig.server.json__tmpl__ +17 -0
  96. package/src/generators/custom-server/schema.d.ts +4 -0
  97. package/src/generators/custom-server/schema.json +30 -0
  98. package/src/generators/cypress-component-configuration/cypress-component-configuration.d.ts +5 -0
  99. package/src/generators/cypress-component-configuration/cypress-component-configuration.js +87 -0
  100. package/src/generators/cypress-component-configuration/schema.d.ts +6 -0
  101. package/src/generators/cypress-component-configuration/schema.json +42 -0
  102. package/src/generators/init/init.d.ts +5 -0
  103. package/src/generators/init/init.js +46 -0
  104. package/src/generators/init/lib/add-plugin.d.ts +2 -0
  105. package/src/generators/init/lib/add-plugin.js +26 -0
  106. package/src/generators/init/schema.d.ts +7 -0
  107. package/src/generators/init/schema.json +34 -0
  108. package/src/generators/library/lib/normalize-options.d.ts +7 -0
  109. package/src/generators/library/lib/normalize-options.js +26 -0
  110. package/src/generators/library/library.d.ts +5 -0
  111. package/src/generators/library/library.js +92 -0
  112. package/src/generators/library/schema.d.ts +28 -0
  113. package/src/generators/library/schema.json +156 -0
  114. package/src/generators/page/page.d.ts +5 -0
  115. package/src/generators/page/page.js +96 -0
  116. package/src/generators/page/schema.d.ts +20 -0
  117. package/src/generators/page/schema.json +111 -0
  118. package/src/migrations/update-15-8-8/add-style-packages.d.ts +3 -0
  119. package/src/migrations/update-15-8-8/add-style-packages.js +23 -0
  120. package/src/migrations/update-16-0-0-add-nx-packages/update-16-0-0-add-nx-packages.d.ts +2 -0
  121. package/src/migrations/update-16-0-0-add-nx-packages/update-16-0-0-add-nx-packages.js +9 -0
  122. package/src/migrations/update-16-3-0/remove-root-build-option.d.ts +2 -0
  123. package/src/migrations/update-16-3-0/remove-root-build-option.js +17 -0
  124. package/src/migrations/update-16-4-0/update-nx-next-dependency.d.ts +2 -0
  125. package/src/migrations/update-16-4-0/update-nx-next-dependency.js +17 -0
  126. package/src/migrations/update-17-2-7/remove-eslint-rules-patch.d.ts +2 -0
  127. package/src/migrations/update-17-2-7/remove-eslint-rules-patch.js +15 -0
  128. package/src/plugins/plugin.d.ts +11 -0
  129. package/src/plugins/plugin.js +182 -0
  130. package/src/utils/add-gitignore-entry.d.ts +2 -0
  131. package/src/utils/add-gitignore-entry.js +17 -0
  132. package/src/utils/add-swc-to-custom-server.d.ts +2 -0
  133. package/src/utils/add-swc-to-custom-server.js +37 -0
  134. package/src/utils/compose-plugins.d.ts +3 -0
  135. package/src/utils/compose-plugins.js +22 -0
  136. package/src/utils/config-invalid-function.fixture.d.ts +0 -0
  137. package/src/utils/config-invalid-function.fixture.js +1 -0
  138. package/src/utils/config-not-a-function.fixture.d.ts +0 -0
  139. package/src/utils/config-not-a-function.fixture.js +1 -0
  140. package/src/utils/config.d.ts +13 -0
  141. package/src/utils/config.js +24 -0
  142. package/src/utils/constants.d.ts +1 -0
  143. package/src/utils/constants.js +4 -0
  144. package/src/utils/create-cli-options.d.ts +1 -0
  145. package/src/utils/create-cli-options.js +13 -0
  146. package/src/utils/create-copy-plugin.d.ts +2 -0
  147. package/src/utils/create-copy-plugin.js +64 -0
  148. package/src/utils/generate-globs.d.ts +5 -0
  149. package/src/utils/generate-globs.js +29 -0
  150. package/src/utils/styles.d.ts +67 -0
  151. package/src/utils/styles.js +67 -0
  152. package/src/utils/types.d.ts +57 -0
  153. package/src/utils/types.js +2 -0
  154. package/src/utils/versions.d.ts +12 -0
  155. package/src/utils/versions.js +15 -0
  156. package/tailwind.d.ts +2 -0
  157. package/tailwind.js +6 -0
  158. package/typings/image.d.ts +12 -0
@@ -0,0 +1,297 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.withNx = exports.forNextVersion = exports.getAliasForProject = exports.getNextConfig = void 0;
4
+ function regexEqual(x, y) {
5
+ return (x instanceof RegExp &&
6
+ y instanceof RegExp &&
7
+ x.source === y.source &&
8
+ x.global === y.global &&
9
+ x.ignoreCase === y.ignoreCase &&
10
+ x.multiline === y.multiline);
11
+ }
12
+ /**
13
+ * Do not remove or rename this function. Production builds inline `with-nx.js` file with a replacement
14
+ * To this function that hard-codes the libsDir.
15
+ */
16
+ function getWithNxContext() {
17
+ const { workspaceRoot, workspaceLayout } = require('@nx/devkit');
18
+ return {
19
+ workspaceRoot,
20
+ libsDir: workspaceLayout().libsDir,
21
+ };
22
+ }
23
+ function getNxContext(graph, target) {
24
+ const { parseTargetString, workspaceRoot } = require('@nx/devkit');
25
+ const projectNode = graph.nodes[target.project];
26
+ const targetConfig = projectNode.data.targets[target.target];
27
+ const targetOptions = targetConfig.options;
28
+ if (target.configuration) {
29
+ Object.assign(targetOptions, targetConfig.configurations[target.configuration]);
30
+ }
31
+ const partialExecutorContext = {
32
+ projectName: target.project,
33
+ targetName: target.target,
34
+ projectGraph: graph,
35
+ configurationName: target.configuration,
36
+ root: workspaceRoot,
37
+ };
38
+ if (targetOptions.devServerTarget) {
39
+ // Executors such as @nx/cypress:cypress define the devServerTarget option.
40
+ return getNxContext(graph, parseTargetString(targetOptions.devServerTarget, partialExecutorContext));
41
+ }
42
+ else if (targetOptions.buildTarget) {
43
+ // Executors such as @nx/next:server or @nx/next:export define the buildTarget option.
44
+ return getNxContext(graph, parseTargetString(targetOptions.buildTarget, partialExecutorContext));
45
+ }
46
+ // Default case, return info for current target.
47
+ // This could be a build using @nx/next:build or run-commands without using our executors.
48
+ return {
49
+ node: graph.nodes[target.project],
50
+ options: targetOptions,
51
+ projectName: target.project,
52
+ targetName: target.target,
53
+ configurationName: target.configuration,
54
+ };
55
+ }
56
+ /**
57
+ * Try to read output dir from project, and default to '.next' if executing outside of Nx (e.g. dist is added to a docker image).
58
+ */
59
+ function withNx(_nextConfig = {}, context = getWithNxContext()) {
60
+ return async (phase) => {
61
+ const { PHASE_PRODUCTION_SERVER, PHASE_DEVELOPMENT_SERVER } = await Promise.resolve().then(() => require('next/constants'));
62
+ // Two scenarios where we want to skip graph creation:
63
+ // 1. Running production server means the build is already done so we just need to start the Next.js server.
64
+ // 2. During graph creation (i.e. create nodes), we won't have a graph to read, and it is not needed anyway since it's a build-time concern.
65
+ //
66
+ // NOTE: Avoid any `require(...)` or `import(...)` statements here. Development dependencies are not available at production runtime.
67
+ if (PHASE_PRODUCTION_SERVER === phase || global.NX_GRAPH_CREATION) {
68
+ const { nx, ...validNextConfig } = _nextConfig;
69
+ return {
70
+ distDir: '.next',
71
+ ...validNextConfig,
72
+ };
73
+ }
74
+ else {
75
+ const { createProjectGraphAsync, joinPathFragments, offsetFromRoot, workspaceRoot, } = require('@nx/devkit');
76
+ let graph;
77
+ try {
78
+ graph = await createProjectGraphAsync();
79
+ }
80
+ catch (e) {
81
+ throw new Error('Could not create project graph. Please ensure that your workspace is valid.', { cause: e });
82
+ }
83
+ const originalTarget = {
84
+ project: process.env.NX_TASK_TARGET_PROJECT,
85
+ target: process.env.NX_TASK_TARGET_TARGET,
86
+ configuration: process.env.NX_TASK_TARGET_CONFIGURATION,
87
+ };
88
+ const { node: projectNode, options, projectName: project, } = getNxContext(graph, originalTarget);
89
+ const projectDirectory = projectNode.data.root;
90
+ // Get next config
91
+ const nextConfig = getNextConfig(_nextConfig, context);
92
+ // For Next.js 13.1 and greater, make sure workspace libs are transpiled.
93
+ forNextVersion('>=13.1.0', () => {
94
+ if (!graph.dependencies[project])
95
+ return;
96
+ const { readTsConfigPaths } = require('@nx/js');
97
+ const { findAllProjectNodeDependencies, } = require('nx/src/utils/project-graph-utils');
98
+ const paths = readTsConfigPaths();
99
+ const deps = findAllProjectNodeDependencies(project);
100
+ nextConfig.transpilePackages ??= [];
101
+ for (const dep of deps) {
102
+ const alias = getAliasForProject(graph.nodes[dep], paths);
103
+ if (alias) {
104
+ nextConfig.transpilePackages.push(alias);
105
+ }
106
+ }
107
+ });
108
+ // process.env.NX_NEXT_OUTPUT_PATH is set when running @nx/next:build
109
+ options.outputPath =
110
+ process.env.NX_NEXT_OUTPUT_PATH || options.outputPath;
111
+ // outputPath may be undefined if using run-commands or other executors other than @nx/next:build.
112
+ // In this case, the user should set distDir in their next.config.js.
113
+ if (options.outputPath && phase !== PHASE_DEVELOPMENT_SERVER) {
114
+ const outputDir = `${offsetFromRoot(projectDirectory)}${options.outputPath}`;
115
+ // If running dev-server, we should keep `.next` inside project directory since Turbopack expects this.
116
+ // See: https://github.com/nrwl/nx/issues/19365
117
+ nextConfig.distDir =
118
+ nextConfig.distDir && nextConfig.distDir !== '.next'
119
+ ? joinPathFragments(outputDir, nextConfig.distDir)
120
+ : joinPathFragments(outputDir, '.next');
121
+ }
122
+ // If we are running a static serve of the Next.js app, we need to change the output to 'export' and the distDir to 'out'.
123
+ if (process.env.NX_SERVE_STATIC_BUILD_RUNNING === 'true') {
124
+ nextConfig.output = 'export';
125
+ nextConfig.distDir = 'out';
126
+ }
127
+ const userWebpackConfig = nextConfig.webpack;
128
+ const { createWebpackConfig } = require('@nx/next/src/utils/config');
129
+ nextConfig.webpack = (a, b) => createWebpackConfig(workspaceRoot, projectDirectory, options.fileReplacements, options.assets)(userWebpackConfig ? userWebpackConfig(a, b) : a, b);
130
+ return nextConfig;
131
+ }
132
+ };
133
+ }
134
+ exports.withNx = withNx;
135
+ function getNextConfig(nextConfig = {}, context = getWithNxContext()) {
136
+ // If `next-compose-plugins` is used, the context argument is invalid.
137
+ if (!context.libsDir || !context.workspaceRoot) {
138
+ context = getWithNxContext();
139
+ }
140
+ const userWebpack = nextConfig.webpack || ((x) => x);
141
+ const { nx, ...validNextConfig } = nextConfig;
142
+ return {
143
+ eslint: {
144
+ ignoreDuringBuilds: true,
145
+ ...(validNextConfig.eslint ?? {}),
146
+ },
147
+ ...validNextConfig,
148
+ webpack: (config, options) => {
149
+ /*
150
+ * Update babel to support our monorepo setup.
151
+ * The 'upward' mode allows the root babel.config.json and per-project .babelrc files to be picked up.
152
+ */
153
+ if (nx?.babelUpwardRootMode) {
154
+ options.defaultLoaders.babel.options.babelrc = true;
155
+ options.defaultLoaders.babel.options.rootMode = 'upward';
156
+ }
157
+ /*
158
+ * Modify the Next.js webpack config to allow workspace libs to use css modules.
159
+ * Note: This would be easier if Next.js exposes css-loader and sass-loader on `defaultLoaders`.
160
+ */
161
+ // Include workspace libs in css/sass loaders
162
+ const includes = [
163
+ require('path').join(context.workspaceRoot, context.libsDir),
164
+ ];
165
+ const nextCssLoaders = config.module.rules.find((rule) => typeof rule.oneOf === 'object');
166
+ // webpack config is not as expected
167
+ if (!nextCssLoaders)
168
+ return config;
169
+ /*
170
+ * 1. Modify css loader to enable module support for workspace libs
171
+ */
172
+ const nextCssLoader = nextCssLoaders.oneOf.find((rule) => rule.sideEffects === false && regexEqual(rule.test, /\.module\.css$/));
173
+ // Might not be found if Next.js webpack config changes in the future
174
+ if (nextCssLoader && nextCssLoader.issuer) {
175
+ nextCssLoader.issuer.or = nextCssLoader.issuer.and
176
+ ? nextCssLoader.issuer.and.concat(includes)
177
+ : includes;
178
+ delete nextCssLoader.issuer.and;
179
+ }
180
+ /*
181
+ * 2. Modify sass loader to enable module support for workspace libs
182
+ */
183
+ const nextSassLoader = nextCssLoaders.oneOf.find((rule) => rule.sideEffects === false &&
184
+ regexEqual(rule.test, /\.module\.(scss|sass)$/));
185
+ // Might not be found if Next.js webpack config changes in the future
186
+ if (nextSassLoader && nextSassLoader.issuer) {
187
+ nextSassLoader.issuer.or = nextSassLoader.issuer.and
188
+ ? nextSassLoader.issuer.and.concat(includes)
189
+ : includes;
190
+ delete nextSassLoader.issuer.and;
191
+ }
192
+ /*
193
+ * 3. Modify error loader to ignore css modules used by workspace libs
194
+ */
195
+ const nextErrorCssModuleLoader = nextCssLoaders.oneOf.find((rule) => rule.use &&
196
+ rule.use.loader === 'error-loader' &&
197
+ rule.use.options &&
198
+ (rule.use.options.reason ===
199
+ 'CSS Modules \u001b[1mcannot\u001b[22m be imported from within \u001b[1mnode_modules\u001b[22m.\n' +
200
+ 'Read more: https://err.sh/next.js/css-modules-npm' ||
201
+ rule.use.options.reason ===
202
+ 'CSS Modules cannot be imported from within node_modules.\nRead more: https://err.sh/next.js/css-modules-npm'));
203
+ // Might not be found if Next.js webpack config changes in the future
204
+ if (nextErrorCssModuleLoader) {
205
+ nextErrorCssModuleLoader.exclude = includes;
206
+ }
207
+ /**
208
+ * 4. Modify css loader to allow global css from node_modules to be imported from workspace libs
209
+ */
210
+ const nextGlobalCssLoader = nextCssLoaders.oneOf.find((rule) => rule.include?.and?.find((include) => regexEqual(include, /node_modules/)));
211
+ // Might not be found if Next.js webpack config changes in the future
212
+ if (nextGlobalCssLoader && nextGlobalCssLoader.issuer) {
213
+ nextGlobalCssLoader.issuer.or = nextGlobalCssLoader.issuer.and
214
+ ? nextGlobalCssLoader.issuer.and.concat(includes)
215
+ : includes;
216
+ delete nextGlobalCssLoader.issuer.and;
217
+ }
218
+ /**
219
+ * 5. Add env variables prefixed with NX_
220
+ */
221
+ addNxEnvVariables(config);
222
+ /**
223
+ * 6. Add SVGR support if option is on.
224
+ */
225
+ // Default SVGR support to be on for projects.
226
+ if (nx?.svgr !== false) {
227
+ config.module.rules.push(
228
+ // Apply rule for svg imports ending in ?url
229
+ {
230
+ test: /\.svg$/i,
231
+ type: 'asset',
232
+ resourceQuery: /url/, // apply to *.svg?url
233
+ },
234
+ // Convert all other svg imports to React components
235
+ {
236
+ test: /\.svg$/i,
237
+ issuer: /\.[jt]sx?$/,
238
+ resourceQuery: { not: [/url/] },
239
+ use: ['@svgr/webpack'],
240
+ });
241
+ }
242
+ return userWebpack(config, options);
243
+ },
244
+ };
245
+ }
246
+ exports.getNextConfig = getNextConfig;
247
+ function getNxEnvironmentVariables() {
248
+ return Object.keys(process.env)
249
+ .filter((env) => /^NX_/i.test(env))
250
+ .reduce((env, key) => {
251
+ env[key] = process.env[key];
252
+ return env;
253
+ }, {});
254
+ }
255
+ /**
256
+ * TODO(v19)
257
+ * @deprecated Use Next.js 9.4+ built-in support for environment variables. Reference https://nextjs.org/docs/pages/api-reference/next-config-js/env
258
+ */
259
+ function addNxEnvVariables(config) {
260
+ const maybeDefinePlugin = config.plugins?.find((plugin) => {
261
+ return plugin.definitions?.['process.env.NODE_ENV'];
262
+ });
263
+ if (maybeDefinePlugin) {
264
+ const env = getNxEnvironmentVariables();
265
+ Object.entries(env)
266
+ .map(([name, value]) => [`process.env.${name}`, `"${value}"`])
267
+ .filter(([name]) => !maybeDefinePlugin.definitions[name])
268
+ .forEach(([name, value]) => (maybeDefinePlugin.definitions[name] = value));
269
+ }
270
+ }
271
+ function getAliasForProject(node, paths) {
272
+ // Match workspace libs to their alias in tsconfig paths.
273
+ for (const [alias, lookup] of Object.entries(paths ?? {})) {
274
+ const lookupContainsDepNode = lookup.some((lookupPath) => lookupPath.startsWith(node?.data?.root) ||
275
+ lookupPath.startsWith('./' + node?.data?.root));
276
+ if (lookupContainsDepNode) {
277
+ return alias;
278
+ }
279
+ }
280
+ return null;
281
+ }
282
+ exports.getAliasForProject = getAliasForProject;
283
+ // Runs a function if the Next.js version satisfies the range.
284
+ function forNextVersion(range, fn) {
285
+ const semver = require('semver');
286
+ const nextJsVersion = require('next/package.json').version;
287
+ if (semver.satisfies(nextJsVersion, range)) {
288
+ fn();
289
+ }
290
+ }
291
+ exports.forNextVersion = forNextVersion;
292
+ // Support for older generated code: `const withNx = require('@nx/next/plugins/with-nx');`
293
+ module.exports = withNx;
294
+ // Support for newer generated code: `const { withNx } = require(...);`
295
+ module.exports.withNx = withNx;
296
+ module.exports.getNextConfig = getNextConfig;
297
+ module.exports.getAliasForProject = getAliasForProject;
@@ -0,0 +1,3 @@
1
+ import { NextConfigFn } from '../src/utils/config';
2
+ import { WithNxOptions } from './with-nx';
3
+ export declare function withStylus(configOrFn: WithNxOptions | NextConfigFn): NextConfigFn;
@@ -0,0 +1,12 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.withStylus = void 0;
4
+ // TODO(v19): Remove file, it is here until users migrate over to SASS manually.
5
+ function withStylus(configOrFn) {
6
+ return async (phase) => {
7
+ throw new Error(`Stylus support has been removed and you should use the built-in SASS support. Remove the "withStylus" plugin from your Next.js config, and rename your files from .styl to .scss.`);
8
+ };
9
+ }
10
+ exports.withStylus = withStylus;
11
+ module.exports = withStylus;
12
+ module.exports.withStylus = withStylus;
@@ -0,0 +1,5 @@
1
+ import { ExecutorContext } from '@nx/devkit';
2
+ import { NextBuildBuilderOptions } from '../../utils/types';
3
+ export default function buildExecutor(options: NextBuildBuilderOptions, context: ExecutorContext): Promise<{
4
+ success: boolean;
5
+ }>;
@@ -0,0 +1,106 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const devkit_1 = require("@nx/devkit");
4
+ const js_1 = require("@nx/js");
5
+ const path_1 = require("path");
6
+ const fs_extra_1 = require("fs-extra");
7
+ const semver_1 = require("semver");
8
+ const fileutils_1 = require("@nx/workspace/src/utilities/fileutils");
9
+ const semver_2 = require("@nx/devkit/src/utils/semver");
10
+ const update_package_json_1 = require("./lib/update-package-json");
11
+ const create_next_config_file_1 = require("./lib/create-next-config-file");
12
+ const check_project_1 = require("./lib/check-project");
13
+ const child_process_1 = require("child_process");
14
+ const create_cli_options_1 = require("../../utils/create-cli-options");
15
+ let childProcess;
16
+ async function buildExecutor(options, context) {
17
+ // Cast to any to overwrite NODE_ENV
18
+ process.env.NODE_ENV ||= 'production';
19
+ const projectRoot = context.projectGraph.nodes[context.projectName].data.root;
20
+ (0, check_project_1.checkPublicDirectory)(projectRoot);
21
+ // Set `__NEXT_REACT_ROOT` based on installed ReactDOM version
22
+ const packageJsonPath = (0, path_1.join)(projectRoot, 'package.json');
23
+ const packageJson = (0, fs_extra_1.existsSync)(packageJsonPath)
24
+ ? (0, devkit_1.readJsonFile)(packageJsonPath)
25
+ : undefined;
26
+ const rootPackageJson = (0, devkit_1.readJsonFile)((0, path_1.join)(context.root, 'package.json'));
27
+ const reactDomVersion = packageJson?.dependencies?.['react-dom'] ??
28
+ rootPackageJson.dependencies?.['react-dom'];
29
+ const hasReact18 = reactDomVersion &&
30
+ (0, semver_1.gte)((0, semver_2.checkAndCleanWithSemver)('react-dom', reactDomVersion), '18.0.0');
31
+ if (hasReact18) {
32
+ process.env['__NEXT_REACT_ROOT'] ||= 'true';
33
+ }
34
+ try {
35
+ await runCliBuild(devkit_1.workspaceRoot, projectRoot, options);
36
+ }
37
+ catch (error) {
38
+ devkit_1.logger.error(`Error occurred while trying to run the build command`);
39
+ devkit_1.logger.error(error);
40
+ return { success: false };
41
+ }
42
+ finally {
43
+ if (childProcess) {
44
+ childProcess.kill();
45
+ }
46
+ }
47
+ if (!(0, fileutils_1.directoryExists)(options.outputPath)) {
48
+ (0, fs_extra_1.mkdir)(options.outputPath);
49
+ }
50
+ const builtPackageJson = (0, js_1.createPackageJson)(context.projectName, context.projectGraph, {
51
+ target: context.targetName,
52
+ root: context.root,
53
+ isProduction: !options.includeDevDependenciesInPackageJson, // By default we remove devDependencies since this is a production build.
54
+ });
55
+ // Update `package.json` to reflect how users should run the build artifacts
56
+ builtPackageJson.scripts = {
57
+ start: 'next start',
58
+ };
59
+ (0, update_package_json_1.updatePackageJson)(builtPackageJson, context);
60
+ (0, devkit_1.writeJsonFile)(`${options.outputPath}/package.json`, builtPackageJson);
61
+ if (options.generateLockfile) {
62
+ const packageManager = (0, devkit_1.detectPackageManager)(context.root);
63
+ const lockFile = (0, js_1.createLockFile)(builtPackageJson, context.projectGraph, packageManager);
64
+ (0, fs_extra_1.writeFileSync)(`${options.outputPath}/${(0, js_1.getLockFileName)(packageManager)}`, lockFile, {
65
+ encoding: 'utf-8',
66
+ });
67
+ }
68
+ // If output path is different from source path, then copy over the config and public files.
69
+ // This is the default behavior when running `nx build <app>`.
70
+ if (options.outputPath.replace(/\/$/, '') !== projectRoot) {
71
+ (0, create_next_config_file_1.createNextConfigFile)(options, context);
72
+ (0, fs_extra_1.copySync)((0, path_1.join)(projectRoot, 'public'), (0, path_1.join)(options.outputPath, 'public'), {
73
+ dereference: true,
74
+ });
75
+ }
76
+ return { success: true };
77
+ }
78
+ exports.default = buildExecutor;
79
+ function runCliBuild(workspaceRoot, projectRoot, options) {
80
+ const { experimentalAppOnly, profile, debug, outputPath } = options;
81
+ // Set output path here since it can also be set via CLI
82
+ // We can retrieve it inside plugins/with-nx
83
+ process.env.NX_NEXT_OUTPUT_PATH ??= outputPath;
84
+ const args = (0, create_cli_options_1.createCliOptions)({ experimentalAppOnly, profile, debug });
85
+ return new Promise((resolve, reject) => {
86
+ childProcess = (0, child_process_1.fork)(require.resolve('next/dist/bin/next'), ['build', ...args], {
87
+ cwd: (0, path_1.resolve)(workspaceRoot, projectRoot),
88
+ stdio: 'inherit',
89
+ env: process.env,
90
+ });
91
+ // Ensure the child process is killed when the parent exits
92
+ process.on('exit', () => childProcess.kill());
93
+ process.on('SIGTERM', () => childProcess.kill());
94
+ childProcess.on('error', (err) => {
95
+ reject(err);
96
+ });
97
+ childProcess.on('exit', (code) => {
98
+ if (code === 0) {
99
+ resolve(code);
100
+ }
101
+ else {
102
+ reject(code);
103
+ }
104
+ });
105
+ });
106
+ }
@@ -0,0 +1 @@
1
+ export declare function checkPublicDirectory(root: string): void;
@@ -0,0 +1,12 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.checkPublicDirectory = void 0;
4
+ const devkit_1 = require("@nx/devkit");
5
+ const fs_extra_1 = require("fs-extra");
6
+ const path_1 = require("path");
7
+ function checkPublicDirectory(root) {
8
+ if ((0, fs_extra_1.readdirSync)((0, path_1.join)(root, 'public')).length === 0) {
9
+ devkit_1.logger.warn('public directory cannot be empty. This may result in errors during the deployment. Consider adding a public/.gitkeep file');
10
+ }
11
+ }
12
+ exports.checkPublicDirectory = checkPublicDirectory;
@@ -0,0 +1,14 @@
1
+ import type { ExecutorContext } from '@nx/devkit';
2
+ import type { NextBuildBuilderOptions } from '../../../utils/types';
3
+ export declare function createNextConfigFile(options: NextBuildBuilderOptions, context: ExecutorContext): void;
4
+ export declare function getWithNxContent({ file, content }?: {
5
+ file: string;
6
+ content: string;
7
+ }): string;
8
+ export declare function findNextConfigPath(dirname: string, userDefinedConfigPath?: string): string;
9
+ export declare function getRelativeFilesToCopy(fileName: string, cwd: string): string[];
10
+ export declare function getRelativeImports({ file, content, }: {
11
+ file: string;
12
+ content: string;
13
+ }): string[];
14
+ export declare function ensureFileExtensions(files: string[], absoluteDir: string): string[];
@@ -0,0 +1,162 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.ensureFileExtensions = exports.getRelativeImports = exports.getRelativeFilesToCopy = exports.findNextConfigPath = exports.getWithNxContent = exports.createNextConfigFile = void 0;
4
+ const devkit_1 = require("@nx/devkit");
5
+ const ts = require("typescript");
6
+ const fs_extra_1 = require("fs-extra");
7
+ const path_1 = require("path");
8
+ const typescript_1 = require("nx/src/utils/typescript");
9
+ function createNextConfigFile(options, context) {
10
+ // Don't overwrite the next.config.js file if output path is the same as the source path.
11
+ if (options.outputPath.replace(/\/$/, '') ===
12
+ context.projectGraph.nodes[context.projectName].data.root) {
13
+ return;
14
+ }
15
+ const projectRoot = context.projectGraph.nodes[context.projectName].data.root;
16
+ const configRelativeToProjectRoot = findNextConfigPath(projectRoot,
17
+ // If user passed a config then it is relative to the workspace root, need to normalize it to be relative to the project root.
18
+ options.nextConfig ? (0, path_1.relative)(projectRoot, options.nextConfig) : undefined);
19
+ const configAbsolutePath = (0, path_1.join)(projectRoot, configRelativeToProjectRoot);
20
+ if (!(0, fs_extra_1.existsSync)(configAbsolutePath)) {
21
+ throw new Error('next.config.js not found');
22
+ }
23
+ // Copy config file and our `.nx-helpers` folder to remove dependency on @nrwl/next for production build.
24
+ const helpersPath = (0, path_1.join)(options.outputPath, '.nx-helpers');
25
+ (0, fs_extra_1.mkdirSync)(helpersPath, { recursive: true });
26
+ (0, fs_extra_1.copyFileSync)((0, path_1.join)(__dirname, '../../../utils/compose-plugins.js'), (0, path_1.join)(helpersPath, 'compose-plugins.js'));
27
+ (0, fs_extra_1.writeFileSync)((0, path_1.join)(helpersPath, 'with-nx.js'), getWithNxContent());
28
+ (0, fs_extra_1.writeFileSync)((0, path_1.join)(helpersPath, 'compiled.js'), `
29
+ const withNx = require('./with-nx');
30
+ module.exports = withNx;
31
+ module.exports.withNx = withNx;
32
+ module.exports.composePlugins = require('./compose-plugins').composePlugins;
33
+ `);
34
+ (0, fs_extra_1.writeFileSync)((0, path_1.join)(options.outputPath, configRelativeToProjectRoot), (0, fs_extra_1.readFileSync)(configAbsolutePath)
35
+ .toString()
36
+ .replace(/["']@nx\/next["']/, `'./.nx-helpers/compiled.js'`)
37
+ // TODO(v17): Remove this once users have all migrated to new @nx scope and import from '@nx/next' not the deep import paths.
38
+ .replace('@nx/next/plugins/with-nx', './.nx-helpers/compiled.js')
39
+ .replace('@nrwl/next/plugins/with-nx', './.nx-helpers/compiled.js'));
40
+ // Find all relative imports needed by next.config.js and copy them to the dist folder.
41
+ const moduleFilesToCopy = getRelativeFilesToCopy(configRelativeToProjectRoot, projectRoot);
42
+ for (const moduleFile of moduleFilesToCopy) {
43
+ (0, fs_extra_1.ensureDirSync)((0, path_1.dirname)((0, path_1.join)(context.root, options.outputPath, moduleFile)));
44
+ // We already generate a build version of package.json in the dist folder.
45
+ if (moduleFile !== 'package.json') {
46
+ (0, fs_extra_1.copyFileSync)((0, path_1.join)(context.root, projectRoot, moduleFile), (0, path_1.join)(context.root, options.outputPath, moduleFile));
47
+ }
48
+ }
49
+ }
50
+ exports.createNextConfigFile = createNextConfigFile;
51
+ function readSource(getFile) {
52
+ return {
53
+ file: getFile(),
54
+ content: (0, fs_extra_1.readFileSync)(getFile()).toString(),
55
+ };
56
+ }
57
+ // Exported for testing
58
+ function getWithNxContent({ file, content } = readSource(() => (0, path_1.join)(__dirname, '../../../../plugins/with-nx.js'))) {
59
+ const withNxSource = ts.createSourceFile(file, content, ts.ScriptTarget.Latest, true);
60
+ const getWithNxContextDeclaration = (0, typescript_1.findNodes)(withNxSource, ts.SyntaxKind.FunctionDeclaration)?.find((node) => node.name?.text === 'getWithNxContext');
61
+ if (getWithNxContextDeclaration) {
62
+ content = (0, devkit_1.applyChangesToString)(content, [
63
+ {
64
+ type: devkit_1.ChangeType.Delete,
65
+ start: getWithNxContextDeclaration.getStart(withNxSource),
66
+ length: getWithNxContextDeclaration.getWidth(withNxSource),
67
+ },
68
+ {
69
+ type: devkit_1.ChangeType.Insert,
70
+ index: getWithNxContextDeclaration.getStart(withNxSource),
71
+ text: (0, devkit_1.stripIndents) `function getWithNxContext() {
72
+ return {
73
+ workspaceRoot: '${devkit_1.workspaceRoot}',
74
+ libsDir: '${(0, devkit_1.workspaceLayout)().libsDir}'
75
+ }
76
+ }`,
77
+ },
78
+ ]);
79
+ }
80
+ return content;
81
+ }
82
+ exports.getWithNxContent = getWithNxContent;
83
+ function findNextConfigPath(dirname, userDefinedConfigPath) {
84
+ if (userDefinedConfigPath) {
85
+ const file = userDefinedConfigPath;
86
+ if ((0, fs_extra_1.existsSync)((0, path_1.join)(dirname, file)))
87
+ return file;
88
+ throw new Error(`Cannot find the Next.js config file: ${userDefinedConfigPath}. Is the path correct in project.json?`);
89
+ }
90
+ const candidates = ['next.config.js', 'next.config.cjs', 'next.config.mjs'];
91
+ for (const candidate of candidates) {
92
+ if ((0, fs_extra_1.existsSync)((0, path_1.join)(dirname, candidate)))
93
+ return candidate;
94
+ }
95
+ throw new Error(`Cannot find any of the following files in your project: ${candidates.join(', ')}. Is this a Next.js project?`);
96
+ }
97
+ exports.findNextConfigPath = findNextConfigPath;
98
+ // Exported for testing
99
+ function getRelativeFilesToCopy(fileName, cwd) {
100
+ const seen = new Set();
101
+ const collected = new Set();
102
+ function doCollect(currFile) {
103
+ // Prevent circular dependencies from causing infinite loop
104
+ if (seen.has(currFile))
105
+ return;
106
+ seen.add(currFile);
107
+ const absoluteFilePath = (0, path_1.join)(cwd, currFile);
108
+ const content = (0, fs_extra_1.readFileSync)(absoluteFilePath).toString();
109
+ const files = getRelativeImports({ file: currFile, content });
110
+ const modules = ensureFileExtensions(files, (0, path_1.dirname)(absoluteFilePath));
111
+ const relativeDirPath = (0, path_1.dirname)(currFile);
112
+ for (const moduleName of modules) {
113
+ const relativeModulePath = (0, path_1.join)(relativeDirPath, moduleName);
114
+ collected.add(relativeModulePath);
115
+ doCollect(relativeModulePath);
116
+ }
117
+ }
118
+ doCollect(fileName);
119
+ return Array.from(collected);
120
+ }
121
+ exports.getRelativeFilesToCopy = getRelativeFilesToCopy;
122
+ // Exported for testing
123
+ function getRelativeImports({ file, content, }) {
124
+ const source = ts.createSourceFile(file, content, ts.ScriptTarget.Latest, true);
125
+ const callExpressionsOrImportDeclarations = (0, typescript_1.findNodes)(source, [
126
+ ts.SyntaxKind.CallExpression,
127
+ ts.SyntaxKind.ImportDeclaration,
128
+ ]);
129
+ const modulePaths = [];
130
+ for (const node of callExpressionsOrImportDeclarations) {
131
+ if (node.kind === ts.SyntaxKind.ImportDeclaration) {
132
+ modulePaths.push(stripOuterQuotes(node.moduleSpecifier.getText(source)));
133
+ }
134
+ else {
135
+ if (node.expression.getText(source) === 'require') {
136
+ modulePaths.push(stripOuterQuotes(node.arguments[0].getText(source)));
137
+ }
138
+ }
139
+ }
140
+ return modulePaths.filter((path) => path.startsWith('.'));
141
+ }
142
+ exports.getRelativeImports = getRelativeImports;
143
+ function stripOuterQuotes(str) {
144
+ return str.match(/^["'](.*)["']/)?.[1] ?? str;
145
+ }
146
+ // Exported for testing
147
+ function ensureFileExtensions(files, absoluteDir) {
148
+ const extensions = ['.js', '.cjs', '.mjs', '.json'];
149
+ return files.map((file) => {
150
+ const providedExt = (0, path_1.extname)(file);
151
+ if (providedExt && extensions.includes(providedExt))
152
+ return file;
153
+ const ext = extensions.find((ext) => (0, fs_extra_1.existsSync)((0, path_1.join)(absoluteDir, file + ext)));
154
+ if (ext) {
155
+ return file + ext;
156
+ }
157
+ else {
158
+ throw new Error(`Cannot find file "${file}" with any of the following extensions: ${extensions.join(', ')}`);
159
+ }
160
+ });
161
+ }
162
+ exports.ensureFileExtensions = ensureFileExtensions;
@@ -0,0 +1,3 @@
1
+ import type { ExecutorContext } from '@nx/devkit';
2
+ import type { PackageJson } from 'nx/src/utils/package-json';
3
+ export declare function updatePackageJson(packageJson: PackageJson, context: ExecutorContext): void;
@@ -0,0 +1,30 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.updatePackageJson = void 0;
4
+ function updatePackageJson(packageJson, context) {
5
+ if (!packageJson.scripts) {
6
+ packageJson.scripts = {};
7
+ }
8
+ if (!packageJson.scripts.start) {
9
+ packageJson.scripts.start = 'next start';
10
+ }
11
+ packageJson.dependencies ??= {};
12
+ // These are always required for a production Next.js app to run.
13
+ // sharp is for next/image https://nextjs.org/docs/messages/sharp-missing-in-production
14
+ // critters is required for experimental optimizing CSS
15
+ const requiredPackages = [
16
+ 'react',
17
+ 'react-dom',
18
+ 'next',
19
+ 'typescript',
20
+ 'sharp',
21
+ 'critters',
22
+ ];
23
+ for (const pkg of requiredPackages) {
24
+ const externalNode = context.projectGraph.externalNodes[`npm:${pkg}`];
25
+ if (externalNode) {
26
+ packageJson.dependencies[pkg] ??= externalNode.data.version;
27
+ }
28
+ }
29
+ }
30
+ exports.updatePackageJson = updatePackageJson;