@commercetools-frontend/mc-scripts 21.3.4 → 21.4.0

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.
package/build/bin/cli.js CHANGED
@@ -69,6 +69,10 @@ const applicationDirectory = fs.realpathSync(process.cwd());
69
69
 
70
70
  (async () => {
71
71
  try {
72
+ // Load dotenv files into the process environment.
73
+ // This is essentially what `dotenv-cli` does, but it's now built into this CLI.
74
+ loadDotEnvFiles(flags);
75
+
72
76
  switch (command) {
73
77
  case 'build':
74
78
  {
@@ -76,11 +80,21 @@ const applicationDirectory = fs.realpathSync(process.cwd());
76
80
  process.env.BABEL_ENV = 'production';
77
81
  process.env.NODE_ENV = 'production';
78
82
  const shouldAlsoCompile = !flags['build-only'];
83
+ const shouldUseExperimentalBundler = process.env.ENABLE_EXPERIMENTAL_VITE_BUNDLER === 'true';
84
+
85
+ if (shouldUseExperimentalBundler) {
86
+ console.log('Experimental Vite bundler enabled! 🚀');
87
+ console.warn('NOTE that the "cdnURL" value is not supported at the moment when using Vite.');
88
+ console.log('');
89
+ }
90
+
79
91
  proxyCommand(command, {
80
- noExit: shouldAlsoCompile
92
+ noExit: shouldAlsoCompile,
93
+ fileName: shouldUseExperimentalBundler ? 'build-vite' : 'build'
81
94
  });
82
95
 
83
96
  if (shouldAlsoCompile) {
97
+ console.log('');
84
98
  proxyCommand('compile-html');
85
99
  }
86
100
 
@@ -112,7 +126,16 @@ const applicationDirectory = fs.realpathSync(process.cwd());
112
126
  // Do this as the first thing so that any code reading it knows the right env.
113
127
  process.env.BABEL_ENV = 'development';
114
128
  process.env.NODE_ENV = 'development';
115
- proxyCommand(command);
129
+ const shouldUseExperimentalBundler = process.env.ENABLE_EXPERIMENTAL_VITE_BUNDLER === 'true';
130
+
131
+ if (shouldUseExperimentalBundler) {
132
+ console.log('Experimental Vite bundler enabled');
133
+ console.log('');
134
+ }
135
+
136
+ proxyCommand(command, {
137
+ fileName: shouldUseExperimentalBundler ? 'start-vite' : 'start'
138
+ });
116
139
  break;
117
140
  }
118
141
 
@@ -166,10 +189,7 @@ function proxyCommand(commandName, {
166
189
  fileName,
167
190
  noExit
168
191
  } = {}) {
169
- // Load dotenv files into the process environment.
170
- // This is essentially what `dotenv-cli` does, but it's now built into this CLI.
171
- loadDotEnvFiles(flags); // Spawn the actual command.
172
-
192
+ // Spawn the actual command.
173
193
  const result = spawn.sync('node', [require.resolve(`../commands/${fileName || commandName}`)].concat(commandArgs), {
174
194
  stdio: 'inherit'
175
195
  }); // Handle exit signals.
@@ -0,0 +1,95 @@
1
+ "use strict";
2
+
3
+ /* eslint-disable react-hooks/rules-of-hooks */
4
+ const fs = require('fs-extra');
5
+
6
+ const path = require('path');
7
+
8
+ const {
9
+ build
10
+ } = require('vite');
11
+
12
+ const pluginGraphql = require('@rollup/plugin-graphql');
13
+
14
+ const pluginReact = require('@vitejs/plugin-react').default;
15
+
16
+ const {
17
+ generateTemplate
18
+ } = require('@commercetools-frontend/mc-html-template');
19
+
20
+ const {
21
+ packageLocation: applicationStaticAssetsPath
22
+ } = require('@commercetools-frontend/assets');
23
+
24
+ const paths = require('../config/paths');
25
+
26
+ const DEFAULT_PORT = parseInt(process.env.HTTP_PORT, 10) || 3001;
27
+
28
+ const execute = async () => {
29
+ // Ensure the `/public` folder exists.
30
+ fs.mkdirSync(paths.appBuild, {
31
+ recursive: true
32
+ }); // Generate `index.html` (template).
33
+
34
+ const appEntryPoint = path.relative(paths.appRoot, paths.entryPoint);
35
+ const html = generateTemplate({
36
+ // Define the module entry point (path relative from the `/public` folder).
37
+ // NOTE: that this is different from the development configuration.
38
+ scriptImports: [`<script type="module" src="/${appEntryPoint}"></script>`]
39
+ }); // Write `index.html` (template) into the `/public` folder.
40
+
41
+ fs.writeFileSync(paths.appIndexHtml, html, {
42
+ encoding: 'utf8'
43
+ }); // TODO: allow to pass additional config options.
44
+ // * `define`
45
+ // * `plugins`
46
+
47
+ await build({
48
+ configFile: false,
49
+ root: paths.appRoot,
50
+ define: {
51
+ 'process.env.DEBUG': JSON.stringify(false),
52
+ 'process.env.NODE_ENV': JSON.stringify(process.env.NODE_ENV)
53
+ },
54
+ build: {
55
+ outDir: 'public',
56
+ assetsDir: '.',
57
+ rollupOptions: {
58
+ // This is necessary to instruct Vite that the `index.html` (template)
59
+ // is located in the `/public` folder.
60
+ // NOTE that after the build, Vite will write the `index.html` (template)
61
+ // at the `/public/public/index.html` location. See `fs.renameSync` below.
62
+ input: paths.appIndexHtml
63
+ }
64
+ },
65
+ server: {
66
+ port: DEFAULT_PORT
67
+ },
68
+ plugins: [pluginGraphql(), pluginReact({
69
+ jsxImportSource: '@emotion/react',
70
+ babel: {
71
+ plugins: ['@emotion/babel-plugin']
72
+ }
73
+ })]
74
+ }); // Rename `/public/public/index.html` to `/public/index.html.template`
75
+
76
+ fs.renameSync( // Because of our custom entry point path (`/public/index.html`),
77
+ // Vite will write the `index.html` to `/public/public/index.html`.
78
+ // We need to move this file to the `/public` folder and rename it
79
+ // to `index.html.template` (as expected by the `compile-html` command).
80
+ path.join(paths.appBuild, 'public/index.html'), paths.appIndexHtmlTemplate); // Clean up nested folder
81
+
82
+ fs.rmdirSync(path.join(paths.appBuild, 'public')); // Copy public assets
83
+
84
+ fs.copySync(path.join(applicationStaticAssetsPath, 'html-page'), paths.appBuild, {
85
+ dereference: true
86
+ });
87
+ };
88
+
89
+ execute().catch(error => {
90
+ if (error && error.message) {
91
+ console.error(error.message);
92
+ }
93
+
94
+ process.exit(1);
95
+ });
@@ -72,7 +72,7 @@ measureFileSizesBeforeBuild(paths.appBuild).then(previousFileSizes => {
72
72
  process.exit(1);
73
73
  }).catch(err => {
74
74
  if (err && err.message) {
75
- console.log(err.message);
75
+ console.error(err.message);
76
76
  }
77
77
 
78
78
  process.exit(1);
@@ -45,6 +45,9 @@ const generateStatic = async () => {
45
45
  };
46
46
 
47
47
  generateStatic().catch(error => {
48
- console.error(error);
48
+ if (error && error.message) {
49
+ console.error(error.message);
50
+ }
51
+
49
52
  process.exit(1);
50
53
  });
@@ -17,7 +17,7 @@ const server = http.createServer((request, response) => {
17
17
  source: '/favicon*',
18
18
  destination: '/favicon.png'
19
19
  }, {
20
- source: '/login',
20
+ source: '/login*',
21
21
  destination: '/login.html'
22
22
  }, {
23
23
  source: '/logout',
@@ -0,0 +1,140 @@
1
+ "use strict";
2
+
3
+ const fs = require('fs-extra');
4
+
5
+ const path = require('path');
6
+
7
+ const {
8
+ createServer
9
+ } = require('vite');
10
+
11
+ const pluginGraphql = require('@rollup/plugin-graphql');
12
+
13
+ const pluginReact = require('@vitejs/plugin-react').default;
14
+
15
+ const {
16
+ processConfig
17
+ } = require('@commercetools-frontend/application-config');
18
+
19
+ const {
20
+ replaceHtmlPlaceholders,
21
+ processHeaders,
22
+ generateTemplate
23
+ } = require('@commercetools-frontend/mc-html-template');
24
+
25
+ const devAuthentication = require('@commercetools-frontend/mc-dev-authentication');
26
+
27
+ const {
28
+ packageLocation: applicationStaticAssetsPath
29
+ } = require('@commercetools-frontend/assets');
30
+
31
+ const paths = require('../config/paths');
32
+
33
+ const DEFAULT_PORT = parseInt(process.env.HTTP_PORT, 10) || 3001;
34
+
35
+ const pluginCustomApplication = applicationConfig => {
36
+ /**
37
+ * @type {import('vite').Plugin}
38
+ */
39
+ return {
40
+ name: 'custom-application',
41
+
42
+ /**
43
+ * @type {import('vite').ServerHook}
44
+ */
45
+ configureServer(server) {
46
+ return () => {
47
+ // Users do not need to have/maintain the `index.html` (as expected by Vite)
48
+ // as it's generated and maintained by the Custom Application CLI.
49
+ // Therefore, the generated `index.html` (template) is written into the `/public`
50
+ // folder so that it's gitignored.
51
+ // As a result, we need to make sure to point the URI path to the correct location.
52
+ server.middlewares.use((req, res, next) => {
53
+ if (req.url === '/index.html') {
54
+ req.url = '/public/index.html';
55
+ }
56
+
57
+ next();
58
+ }); // Handle auth routes for internal local development.
59
+
60
+ server.middlewares.use(devAuthentication.middlewares.createMcDevAuthenticationMiddleware(applicationConfig));
61
+ };
62
+ },
63
+
64
+ /**
65
+ * @type {import('vite').IndexHtmlTransformHook}
66
+ */
67
+ transformIndexHtml(rawHtml, _ctx) {
68
+ const compiledHeaders = processHeaders(applicationConfig);
69
+ const enhancedLocalEnv = Object.assign({}, applicationConfig.env, // Now that the app config is defined as a `env.json`, when we start the FE app
70
+ // to point to the local backend API by passing the `MC_API_URL` env does not
71
+ // work anymore). To make it work again, we can override the `env.json` config
72
+ // with the env variable before injecting the values into the index.html.
73
+ // NOTE: this is only necessary for development.
74
+ process.env.MC_API_URL ? {
75
+ mcApiUrl: process.env.MC_API_URL
76
+ } : {}); // Resolve the placeholders of the `index.html` (template) file, before serving it.
77
+
78
+ const html = replaceHtmlPlaceholders(rawHtml, {
79
+ env: enhancedLocalEnv,
80
+ headers: compiledHeaders
81
+ });
82
+ return html;
83
+ }
84
+
85
+ };
86
+ };
87
+
88
+ const execute = async () => {
89
+ // Load the Custom Application config file first.
90
+ const applicationConfig = processConfig(); // Ensure the `/public` folder exists.
91
+
92
+ fs.mkdirSync(paths.appBuild, {
93
+ recursive: true
94
+ }); // Generate `index.html` (template).
95
+
96
+ const appEntryPoint = path.relative(paths.appRoot, paths.entryPoint);
97
+ const html = generateTemplate({
98
+ // Define the module entry point (path relative to the `/public` folder).
99
+ // NOTE: that this is different from the production configuration.
100
+ scriptImports: [`<script type="module" src="/../${appEntryPoint}"></script>`]
101
+ }); // Write `index.html` (template) into the `/public` folder.
102
+
103
+ fs.writeFileSync(paths.appIndexHtml, html, {
104
+ encoding: 'utf8'
105
+ }); // TODO: allow to pass additional config options.
106
+ // * `define`
107
+ // * `plugins`
108
+
109
+ const server = await createServer({
110
+ configFile: false,
111
+ root: paths.appRoot,
112
+ define: {
113
+ 'process.env.DEBUG': JSON.stringify(false),
114
+ 'process.env.NODE_ENV': JSON.stringify(process.env.NODE_ENV)
115
+ },
116
+ server: {
117
+ port: DEFAULT_PORT
118
+ },
119
+ plugins: [pluginGraphql(), pluginReact({
120
+ jsxImportSource: '@emotion/react',
121
+ babel: {
122
+ plugins: ['@emotion/babel-plugin']
123
+ }
124
+ }), pluginCustomApplication(applicationConfig)]
125
+ });
126
+ await server.listen(); // Copy public assets to `/public` folder (even in development).
127
+
128
+ fs.copySync(path.join(applicationStaticAssetsPath, 'html-page'), paths.appBuild, {
129
+ dereference: true
130
+ });
131
+ server.printUrls();
132
+ };
133
+
134
+ execute().catch(error => {
135
+ if (error && error.message) {
136
+ console.error(error.message);
137
+ }
138
+
139
+ process.exit(1);
140
+ });
@@ -72,8 +72,6 @@ choosePort(HOST, DEFAULT_PORT).then(port => {
72
72
  }); // Serve webpack assets generated by the compiler over a web sever.
73
73
 
74
74
  const serverConfig = createDevServerConfig({
75
- allowedHost: urls.localUrlForBrowser,
76
- contentBase: paths.appBuild,
77
75
  port,
78
76
  publicPath: config.output.publicPath
79
77
  });
@@ -103,7 +101,7 @@ choosePort(HOST, DEFAULT_PORT).then(port => {
103
101
  }
104
102
  }).catch(err => {
105
103
  if (err && err.message) {
106
- console.log(err.message);
104
+ console.error(err.message);
107
105
  }
108
106
 
109
107
  process.exit(1);
@@ -262,7 +262,7 @@ module.exports = function createWebpackConfigForDevelopment(options = {}) {
262
262
  test: function testForNormalCssFiles(fileName) {
263
263
  return (// Use this only for plain CSS.
264
264
  // For css-modules, see loader above.
265
- fileName.endsWith('.css') && !fileName.endsWith('.mod.css')
265
+ fileName.endsWith('.css') && !(fileName.endsWith('.mod.css') || fileName.endsWith('.module.css'))
266
266
  );
267
267
  },
268
268
  // "postcss" loader applies autoprefixer to our CSS.
@@ -281,7 +281,7 @@ module.exports = function createWebpackConfigForProduction(options = {}) {
281
281
  test: function testForNormalCssFiles(fileName) {
282
282
  return (// Use this only for plain CSS.
283
283
  // For css-modules, see loader above.
284
- fileName.endsWith('.css') && !fileName.endsWith('.mod.css')
284
+ fileName.endsWith('.css') && !(fileName.endsWith('.mod.css') || fileName.endsWith('.module.css'))
285
285
  );
286
286
  },
287
287
  // "postcss" loader applies autoprefixer to our CSS.
@@ -1,7 +1,5 @@
1
1
  "use strict";
2
2
 
3
- const errorOverlayMiddleware = require('react-dev-utils/errorOverlayMiddleware');
4
-
5
3
  const {
6
4
  processConfig
7
5
  } = require('@commercetools-frontend/application-config');
@@ -26,8 +24,6 @@ const sockPath = process.env.WDS_SOCKET_PATH; // default: '/ws'
26
24
  const sockPort = process.env.WDS_SOCKET_PORT;
27
25
 
28
26
  module.exports = ({
29
- allowedHost,
30
- contentBase,
31
27
  port,
32
28
  publicPath
33
29
  }) => ({
@@ -62,37 +58,11 @@ module.exports = ({
62
58
  // Enable HTTPS if the HTTPS environment variable is set to 'true'
63
59
  // `proxy` is run between `before` and `after` `webpack-dev-server` hooks
64
60
  setupMiddlewares(middlewares, devServer) {
65
- var _applicationConfig$en, _applicationConfig$en2;
66
-
67
61
  if (!devServer) {
68
62
  throw new Error('webpack-dev-server is not defined');
69
- } // This lets us open files from the runtime error overlay.
70
-
71
-
72
- middlewares.unshift(errorOverlayMiddleware());
73
- devServer.app.set('views', devAuthentication.views);
74
- devServer.app.set('view engine', devAuthentication.config.viewEngine);
75
- devServer.app.post('/api/graphql', (request, response) => {
76
- response.statusCode = 404;
77
- response.setHeader('Content-Type', 'application/json');
78
- response.end(JSON.stringify({
79
- message: `This GraphQL endpoint is only available in production in the [Merchant Center Proxy Router](https://docs.commercetools.com/custom-applications/concepts/merchant-center-proxy-router). Please check that you are not calling this endpoint in development mode.`
80
- }));
81
- });
82
-
83
- if ((_applicationConfig$en = applicationConfig.env.__DEVELOPMENT__) !== null && _applicationConfig$en !== void 0 && (_applicationConfig$en2 = _applicationConfig$en.oidc) !== null && _applicationConfig$en2 !== void 0 && _applicationConfig$en2.authorizeUrl) {
84
- var _applicationConfig$en3, _applicationConfig$en4;
85
-
86
- // Handle login page for OIDC workflow when developing against a local MC API.
87
- if ((_applicationConfig$en3 = applicationConfig.env.__DEVELOPMENT__) !== null && _applicationConfig$en3 !== void 0 && (_applicationConfig$en4 = _applicationConfig$en3.oidc) !== null && _applicationConfig$en4 !== void 0 && _applicationConfig$en4.authorizeUrl.startsWith('http://localhost')) {
88
- devServer.app.get('/login/authorize', devAuthentication.middlewares.createLoginMiddleware(applicationConfig.env));
89
- }
90
- } else {
91
- devServer.app.get('/login', devAuthentication.middlewares.createLoginMiddleware(applicationConfig.env)); // Intercept the /logout page and "remove" the auth cookie value
92
-
93
- devServer.app.get('/logout', devAuthentication.middlewares.createLogoutMiddleware(applicationConfig.env));
94
63
  }
95
64
 
65
+ middlewares.push(devAuthentication.middlewares.createMcDevAuthenticationMiddleware(applicationConfig));
96
66
  return middlewares;
97
67
  }
98
68
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@commercetools-frontend/mc-scripts",
3
- "version": "21.3.4",
3
+ "version": "21.4.0",
4
4
  "description": "Configuration and scripts for developing a MC application",
5
5
  "bugs": "https://github.com/commercetools/merchant-center-application-kit/issues",
6
6
  "repository": {
@@ -33,10 +33,12 @@
33
33
  "@commercetools-frontend/assets": "21.0.0",
34
34
  "@commercetools-frontend/babel-preset-mc-app": "21.3.4",
35
35
  "@commercetools-frontend/constants": "21.3.4",
36
- "@commercetools-frontend/mc-dev-authentication": "21.0.0",
37
- "@commercetools-frontend/mc-html-template": "21.3.4",
36
+ "@commercetools-frontend/mc-dev-authentication": "21.4.0",
37
+ "@commercetools-frontend/mc-html-template": "21.4.0",
38
38
  "@pmmmwh/react-refresh-webpack-plugin": "0.5.4",
39
+ "@rollup/plugin-graphql": "1.1.0",
39
40
  "@svgr/webpack": "6.2.1",
41
+ "@vitejs/plugin-react": "1.3.0",
40
42
  "autoprefixer": "^10.4.4",
41
43
  "babel-loader": "8.2.4",
42
44
  "browserslist": "^4.20.2",
@@ -73,6 +75,7 @@
73
75
  "terser-webpack-plugin": "5.3.1",
74
76
  "thread-loader": "3.0.4",
75
77
  "url": "^0.11.0",
78
+ "vite": "2.9.1",
76
79
  "webpack": "5.72.0",
77
80
  "webpack-bundle-analyzer": "4.5.0",
78
81
  "webpack-dev-server": "4.8.1",