Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(cli): add opt-in experimental support for Vite bundler #2568

Merged
merged 10 commits into from Apr 28, 2022
5 changes: 5 additions & 0 deletions .changeset/dry-spies-vanish.md
@@ -0,0 +1,5 @@
---
'@commercetools-frontend/mc-dev-authentication': patch
---

Expose new middleware `createMcDevAuthenticationMiddleware`. This is mostly used for internal development.
25 changes: 25 additions & 0 deletions .changeset/fair-poets-watch.md
@@ -0,0 +1,25 @@
---
'@commercetools-frontend/mc-dev-authentication': minor
'@commercetools-frontend/mc-html-template': minor
'@commercetools-frontend/mc-scripts': minor
---

Enable opt-in support for using [Vite.js](https://vitejs.dev/) bundler. To enable it, set the environment variable `ENABLE_EXPERIMENTAL_VITE_BUNDLER="true"` in your dotenv file.

# Why Vite

Vite (French word for "quick", pronounced /vit/, like "veet") is a build tool that aims to provide a faster and leaner development experience for modern web projects.

You can learn more about the rationale behind the project in the [Why Vite](https://vitejs.dev/guide/why.html) documentation.

# Native ES Modules support

Vite is optimized for using native [ES Modules](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Modules) via `<script type="module">` tags and ES Modules dynamic import.

# CLI compatibility

All the `mc-scripts` CLI commands are fully compatible with the new bundler, so you can continue using them as before.

## Unsupported features

The `cdnUrl` value is not supported at the moment when using Vite.
6 changes: 6 additions & 0 deletions .changeset/forty-actors-retire.md
@@ -0,0 +1,6 @@
---
'merchant-center-application-template-starter': patch
'playground': patch
---

Rename files using JSX to `.jsx`
5 changes: 5 additions & 0 deletions .changeset/silver-owls-check.md
@@ -0,0 +1,5 @@
---
'playground': patch
---

Use new experimental bundler
5 changes: 5 additions & 0 deletions .changeset/sixty-hotels-kneel.md
@@ -0,0 +1,5 @@
---
'@commercetools-frontend/mc-html-template': patch
---

Extract html template into separate file for better reusability.
4 changes: 4 additions & 0 deletions @types-extensions/css/index.d.ts
Expand Up @@ -2,3 +2,7 @@ declare module '*.mod.css' {
const classes: { [key: string]: string };
export default classes;
}
declare module '*.module.css' {
const classes: { [key: string]: string };
export default classes;
}
@@ -1,4 +1,4 @@
import React from 'react';
import { lazy } from 'react';
import {
ApplicationShell,
setupGlobalErrorListener,
Expand All @@ -8,7 +8,7 @@ import loadMessages from '../../load-messages';
// Here we split up the main (app) bundle with the actual application business logic.
// Splitting by route is usually recommended and you can potentially have a splitting
// point for each route. More info at https://reactjs.org/docs/code-splitting.html
const AsyncApplicationRoutes = React.lazy(() =>
const AsyncApplicationRoutes = lazy(() =>
import('../../routes' /* webpackChunkName: "routes" */)
);

Expand Down
@@ -0,0 +1,76 @@
const path = require('path');
const pug = require('pug');
const { logout } = require('../routes');

const compileLoginView = pug.compileFile(
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not sure how you feel about it but using pug for these two feels a bit like uncalled-for complexity. For me personally, it doesn't ease anything. It's unrelated to the PR but I wounder if we could just remove pug? What are your thoughts?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't have a strong reason to keep using pug either. What would be the alternative? Plain old HTML?

path.join(__dirname, '../views/login.pug')
);
const compileLogoutView = pug.compileFile(
path.join(__dirname, '../views/logout.pug')
);

function createMcDevAuthenticationMiddleware(applicationConfig) {
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is an "aggregated" middleware for handling login/logout requests from developing against the local MC API.

This is only useful for internal teams.

const htmlLogin = compileLoginView({ env: applicationConfig.env });
const htmlLogout = compileLogoutView({ env: applicationConfig.env });
Comment on lines +13 to +14
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Instead of relying of writing/reading these pages from disk, we can simply handle it in memory.

Here we compile the pages and serve them when needed.


const isDevAuthenticationMiddlewareDisabled =
String(applicationConfig.env.disableAuthRoutesOfDevServer) === 'true' ||
applicationConfig.env.servedByProxy;

/**
* @type {import('express').RequestHandler}
*/
return (request, response, next) => {
if (request.originalUrl === '/api/graphql') {
response.statusCode = 404;
response.setHeader('Content-Type', 'application/json');
response.end(
JSON.stringify({
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.`,
})
);
return;
}

if (applicationConfig.env.__DEVELOPMENT__?.oidc?.authorizeUrl) {
// Handle login page for OIDC workflow when developing against a local MC API.
if (
applicationConfig.env.__DEVELOPMENT__?.oidc?.authorizeUrl.startsWith(
'http://localhost'
)
) {
if (request.originalUrl.startsWith('/login/authorize')) {
if (isDevAuthenticationMiddlewareDisabled) {
next();
} else {
response.end(htmlLogin);
}
return;
}
}
emmenko marked this conversation as resolved.
Show resolved Hide resolved
} else {
if (request.originalUrl === '/login') {
if (isDevAuthenticationMiddlewareDisabled) {
next();
} else {
response.end(htmlLogin);
}
return;
}
if (request.originalUrl === '/logout') {
logout(response);

if (isDevAuthenticationMiddlewareDisabled) {
next();
} else {
response.end(htmlLogout);
}
return;
}
}

next();
};
}

module.exports = createMcDevAuthenticationMiddleware;
2 changes: 2 additions & 0 deletions packages/mc-dev-authentication/middlewares/index.js
@@ -1,7 +1,9 @@
const createLoginMiddleware = require('./create-login-middleware');
const createLogoutMiddleware = require('./create-logout-middleware');
Comment on lines 1 to 2
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These two are kept for backwards compatibility

const createMcDevAuthenticationMiddleware = require('./create-mc-dev-authentication-middleware');

module.exports = {
createLoginMiddleware,
createLogoutMiddleware,
createMcDevAuthenticationMiddleware,
};
12 changes: 0 additions & 12 deletions packages/mc-dev-authentication/transformer-local.js
Expand Up @@ -24,18 +24,6 @@ module.exports = ({ env }) => {
const loginViewHtml = compileLoginView({ env });
const logoutViewHtml = compileLogoutView({ env });

fs.copyFileSync(
path.join(__dirname, 'views', 'login.css'),
path.join(paths.appBuild, 'login.css')
);
fs.copyFileSync(
path.join(__dirname, 'views', 'login.js'),
path.join(paths.appBuild, 'login.js')
);
fs.copyFileSync(
path.join(__dirname, 'views', 'logout.js'),
path.join(paths.appBuild, 'logout.js')
);
Comment on lines -27 to -38
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This was never really necessary, as the CSS and JS are included in the HTML page.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Odd. Maybe a left over from a refactoring. Thanks for removing.

fs.writeFileSync(
path.join(paths.appBuild, 'login.html'),
loginViewHtml,
Expand Down
72 changes: 72 additions & 0 deletions packages/mc-html-template/html-docs/application.html
@@ -0,0 +1,72 @@
<!DOCTYPE html>
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Moving this in to a proper HTML file makes it a bit "easier" to maintain and read (syntax highlighting) instead of being a huge block of string.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Agreed.

<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no">
<meta name="referrer" content="no-referrer">

<meta http-equiv="Content-Security-Policy" content="__CSP__">

<!-- Preconnects -->
<link rel="preconnect" href="__CDN_URL__">
<link rel="preconnect" href="__MC_API_URL__">

<!-- Fav and touch icons -->
<link rel="shortcut icon" type="image/png" href="__CDN_URL__favicon.png">
<!-- Standard iPhone -->
<link rel="apple-touch-icon" sizes="57x57" href="__CDN_URL__favicon_57x57px.png">
<link rel="apple-touch-icon-precomposed" sizes="57x57" href="__CDN_URL__favicon_57x57px.png">
<!-- Standard iPad -->
<link rel="apple-touch-icon" sizes="72x72" href="__CDN_URL__favicon_72x72px.png">
<link rel="apple-touch-icon-precomposed" sizes="72x72" href="__CDN_URL__favicon_72x72px.png">
<!-- Retina iPad -->
<link rel="apple-touch-icon" sizes="144x144" href="__CDN_URL__favicon_144x144px.png">
<link rel="apple-touch-icon-precomposed" sizes="144x144" href="__CDN_URL__favicon_144x144px.png">

<!-- Fonts -->
<link href='https://fonts.googleapis.com/css?family=Open+Sans:300,300i,400,400i,600,600i,700,700i' rel='stylesheet' type='text/css'>

__APPLICATION_CSS_IMPORTS__
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also unrelated but given we started using es6-template-strings in other parts I wonder if it could make sense to use it too. Also an improvements we can make separately if we want to.


<title>Merchant Center</title>
</head>
<body>
<noscript>You need to enable JavaScript to run this app.</noscript>

<div id="app-loader">
<!-- Loading screen styles -->
__LOADING_SCREEN_CSS__

<div class="loading-screen loading-screen--hidden">
<svg class="loading-spinner" viewBox="0 0 40 40">
<path class="loading-spinner-circle" d="M20.201,5.169c-8.254,0-14.946,6.692-14.946,14.946c0,8.255,6.692,14.946, 14.946,14.946 s14.946-6.691,14.946-14.946C35.146,11.861,28.455,5.169,20.201,5.169z M20.201,31.749c-6.425,0-11.634-5.208-11.634-11.634c0-6.425,5.209-11.634,11.634-11.634c6.425,0,11.633,5.209,11.633,11.634C31.834,26.541,26.626,31.749,20.201,31.749z"></path>
<path class="loading-spinner-pointer" d="M26.013,10.047l1.654-2.866c-2.198-1.272-4.743-2.012-7.466-2.012h0v3.312h0 C22.32,8.481,24.301,9.057,26.013,10.047z"></path>
</svg>
<svg width="200" height="29" xmlns="http://www.w3.org/2000/svg">
<g fill="none" fill-rule="evenodd">
<path d="M38.342 20.486c1.102 0 1.738-.073 3.133-.367l.343 2.35c-1.077.293-2.276.44-3.476.44-5.358 0-6.9-3.353-6.9-7.268.049-3.818 2.35-7.048 6.876-7.048 1.2 0 2.227.147 3.475.465l-.465 2.325c-1.321-.294-2.104-.342-2.936-.342-2.839.048-4.234 2.153-4.283 4.6 0 2.422.906 4.845 4.233 4.845M49.304 20.51c2.814-.024 3.72-2.3 3.72-4.77-.024-2.253-.98-4.798-3.744-4.798-2.692.025-3.745 2.521-3.745 4.797 0 2.569 1.126 4.771 3.769 4.771zm0-11.917c4.405.025 6.363 3.304 6.363 7.146 0 3.744-1.689 7.096-6.387 7.12-4.601-.048-6.363-3.376-6.363-7.12 0-3.842 1.982-7.097 6.387-7.146zM73.896 22.615v-8.81c0-2.226-.832-2.838-2.227-2.838-.954 0-2.031.539-3.01 1.346.05.294.073.88.073 1.052v9.25h-2.74v-8.907c0-2.227-.661-2.766-2.056-2.766-.88 0-2.104.588-3.157 1.371v10.302h-2.716V8.838h2.716v1.174c.832-.66 2.154-1.419 3.597-1.443 1.91-.024 3.01.636 3.623 1.664 1.125-1.052 2.79-1.64 4.062-1.664 4.478-.074 4.55 3.523 4.55 5.04v9.006h-2.715M95.427 22.615v-8.81c0-2.226-.831-2.838-2.226-2.838-.955 0-2.032.539-3.01 1.346.049.294.073.88.073 1.052v9.25h-2.74v-8.907c0-2.227-.662-2.766-2.057-2.766-.88 0-2.104.588-3.157 1.371v10.302h-2.716V8.838h2.716v1.174c.833-.66 2.154-1.419 3.598-1.443 1.908-.024 3.01.636 3.622 1.664 1.126-1.052 2.79-1.64 4.062-1.664 4.478-.074 4.551 3.523 4.551 5.04v9.006h-2.716M103.035 14.124h6.044c-.098-2.79-1.492-3.353-2.789-3.353-2.056-.024-3.01 1.37-3.255 3.353zm7.782 5.97l.416 2.227c-1.224.416-2.912.612-4.233.612-5.433 0-6.755-3.646-6.755-7.292s1.616-7.023 6.167-7.023c2.814 0 5.163 1.737 5.188 6.166l-.025 1.444h-8.662c.049 2.692 1.493 4.331 4.209 4.331 1.076 0 2.202-.122 3.695-.465zM121.582 11.358a7.379 7.379 0 0 0-1.762-.195c-1.689-.025-2.57.808-3.206 1.468v9.984h-2.716V8.838h2.716v1.223a4.503 4.503 0 0 1 3.182-1.395 6.356 6.356 0 0 1 2.275.368l-.489 2.324M129.533 20.486c1.102 0 1.738-.073 3.132-.367l.344 2.35c-1.077.293-2.276.44-3.476.44-5.359 0-6.9-3.353-6.9-7.268.049-3.818 2.349-7.048 6.876-7.048 1.2 0 2.227.147 3.475.465l-.465 2.325c-1.322-.294-2.105-.342-2.936-.342-2.839.048-4.234 2.153-4.284 4.6 0 2.422.907 4.845 4.234 4.845M136.898 14.124h6.045c-.098-2.79-1.493-3.353-2.79-3.353-2.056-.024-3.01 1.37-3.255 3.353zm7.782 5.97l.416 2.227c-1.224.416-2.912.612-4.234.612-5.432 0-6.754-3.646-6.754-7.292s1.616-7.023 6.167-7.023c2.815 0 5.164 1.737 5.188 6.166l-.024 1.444h-8.663c.049 2.692 1.493 4.331 4.209 4.331 1.076 0 2.202-.122 3.695-.465zM154.662 11.09h-3.744v6.68c0 1.394.171 2.374 1.59 2.569.784.074 1.591 0 2.374-.098l.171 2.35c-.807.146-1.957.17-2.422.17-3.206-.121-4.405-1.761-4.405-4.33v-7.342h-1.982V9.205l1.982-.22V5.779h2.692v3.06h3.744v2.25M162.565 20.51c2.815-.024 3.72-2.3 3.72-4.77-.024-2.253-.979-4.798-3.744-4.798-2.692.025-3.745 2.521-3.745 4.797 0 2.569 1.127 4.771 3.77 4.771zm0-11.917c4.405.025 6.363 3.304 6.363 7.146 0 3.744-1.689 7.096-6.387 7.12-4.6-.048-6.363-3.376-6.363-7.12 0-3.842 1.982-7.097 6.387-7.146zM177.197 20.51c2.814-.024 3.72-2.3 3.72-4.77-.025-2.253-.98-4.798-3.744-4.798-2.692.025-3.745 2.521-3.745 4.797 0 2.569 1.126 4.771 3.769 4.771zm0-11.917c4.405.025 6.363 3.304 6.363 7.146 0 3.744-1.69 7.096-6.387 7.12-4.601-.048-6.363-3.376-6.363-7.12 0-3.842 1.982-7.097 6.387-7.146zM185.71 22.615h2.619V3.919h-2.619zM191.094 19.948c1.542.391 2.985.587 3.89.587 1.078 0 2.179-.22 2.252-1.517.074-1.37-1.346-1.787-2.96-2.472-1.836-.758-3.818-1.786-3.77-4.331.05-1.273.808-3.769 4.87-3.646 1.224.024 2.692.22 3.915.538l-.464 2.251c-1.444-.342-2.52-.49-3.573-.513-1.175 0-2.08.367-2.129 1.468-.024.93.71 1.42 2.52 2.153 1.836.759 4.43 1.738 4.308 4.625-.074 1.835-1.273 3.842-4.968 3.793-1.175-.024-3.059-.171-4.453-.66l.562-2.276" fill="#27373C"/>
<path d="M.349 22.312a.601.601 0 0 0-.002 1.091l11.663 5.46c.156.074.325.112.493.113V16.787c-.173 0-.346.037-.508.112L.35 22.312" fill="#E3712C"/>
<path d="M12.503 16.787v12.19c.18.003.361-.035.528-.113l11.63-5.444a.6.6 0 0 0-.002-1.09L13.011 16.9a1.2 1.2 0 0 0-.508-.113" fill="#EBA13B"/>
<path d="M0 6.363a.596.596 0 0 0 .347.546l11.663 5.46a1.194 1.194 0 0 0 .93.039l.327-.152c1.203-.56.406-.187 11.394-5.33a.6.6 0 0 0-.002-1.091L13.011.405a1.205 1.205 0 0 0-1.016 0L.35 5.818A.603.603 0 0 0 0 6.363" fill="#23A486"/>
<path d="M12.503 13.168v3.62c-.173 0-.346.036-.508.111L.35 22.312a.601.601 0 0 0-.348.545L0 6.77v-.407c0 .234.134.447.346.546l11.664 5.46a1.194 1.194 0 0 0 .93.039l-.02.009c-.362.167-.417.334-.417.75" fill="#CCCCC7"/>
</g>
</svg>
<p class="long-loading-notice long-loading-notice--hidden">Sorry, this is taking an unusually long time.</p>
</div>
</div>
<div id="app"></div>

<!-- Loading screen handling -->
__LOADING_SCREEN_JS__

<!-- Application globals -->
<script>window.app = __APPLICATION_ENVIRONMENT__;</script>

<!-- Tracking scripts (load before application bundles) -->
__DATALAYER_JS__
__GTM_SCRIPT__

<!-- Main application chunks -->
__APPLICATION_SCRIPT_IMPORTS__
</body>
</html>
11 changes: 11 additions & 0 deletions packages/mc-html-template/html-scripts/public-path.js
@@ -0,0 +1,11 @@
window.__dynamicImportHandler__ = function (importer) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe we can add a comment to the file what this does and why its needed for our future selfs? I can follow along but wonder if we won't forget in a year or two.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Update: after reading the whole PR the comments are sufficient. It's just that one when reviewing ends up here first :)

return `${window.app.cdnUrl.replace(/\/$/, '')}/${importer.replace(
/^(\.\/)?/,
''
)}`;
};
window.__dynamicImportPreload__ = function (preloads) {
return preloads.map(
(preload) => `${window.app.cdnUrl.replace(/\/$/, '')}/${preload}`
);
};
Comment on lines +1 to +11
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is the equivalent of Webpack's __webpack_public_path__.

12 changes: 3 additions & 9 deletions packages/mc-html-template/package.json
Expand Up @@ -15,15 +15,7 @@
"access": "public"
},
"main": "./build/index.js",
"files": [
"build",
"html-scripts",
"html-styles",
"webpack.js",
"package.json",
"LICENSE",
"README.md"
],
"files": ["build", "webpack.js", "package.json", "LICENSE", "README.md"],
"scripts": {
"build": "rimraf build && babel src --out-dir build",
"build:bundles:watch": "yarn build -w"
Expand All @@ -41,6 +33,7 @@
"devDependencies": {
"@babel/plugin-transform-runtime": "^7.17.0",
"@babel/preset-env": "^7.16.11",
"babel-plugin-preval": "^5.1.0",
"rimraf": "3.0.2"
},
"engines": {
Expand All @@ -61,6 +54,7 @@
]
],
"plugins": [
"preval",
[
"@babel/plugin-transform-runtime",
{
Expand Down