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
Conversation
🦋 Changeset detectedLatest commit: e2396e1 The changes in this PR will be included in the next version bump. This PR includes changesets to release 5 packages
Not sure what this means? Click here to learn what changesets are. Click here if you're a maintainer who wants to add another changeset to this PR |
The latest updates on your projects. Learn more about Vercel for Git ↗︎
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Really promising. Thanks for spending time on this!
Just as a general question: is your vision for the mc-scripts
and bundling in general that app-kit always supports the (or one) most commonly used bundler while from time to time we transition to it or would you also see supporting different bundlers at the same time on the long-term?
.changeset/fair-poets-watch.md
Outdated
'@commercetools-frontend/mc-scripts': minor | ||
--- | ||
|
||
Enable opt-in support for experimental bundler (using [Vite.js](https://vitejs.dev/)). To enable it, set the environment variable `ENABLE_EXPERIMENTAL_BUNDLER="true"` in your dotenv file. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Enable opt-in support for experimental bundler (using [Vite.js](https://vitejs.dev/)). To enable it, set the environment variable `ENABLE_EXPERIMENTAL_BUNDLER="true"` in your dotenv file. | |
Enable opt-in support for experimental bundler (using [Vite.js](https://vitejs.dev/)). To enable it, set the environment variable `ENABLE_EXPERIMENTAL_VITE_BUNDLING=true"` in your dotenv file. |
Just as we might have the flag for a bit to make it really clear what it turns on.
Good question. I probably wouldn't support multiple different bundles. At least I don't see a need for that. So in this case, if we are happy with Vite we will then make it the default and remove the Webpack stuff. |
I frankly also do not see the need. I just remembered us having a discussion around it being an option a while ago. Supporting multiple in the end costs maintenance and it would be hard to weigh the trade offs and allow users make informed decisions. So I think recommending one is probably easiest for both sides. |
dc15710
to
33ffaef
Compare
path.join(__dirname, '../views/logout.pug') | ||
); | ||
|
||
function createMcDevAuthenticationMiddleware(applicationConfig) { |
There was a problem hiding this comment.
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 }); |
There was a problem hiding this comment.
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 createLoginMiddleware = require('./create-login-middleware'); | ||
const createLogoutMiddleware = require('./create-logout-middleware'); |
There was a problem hiding this comment.
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
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') | ||
); |
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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.
@@ -0,0 +1,72 @@ | |||
<!DOCTYPE html> |
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Agreed.
window.__dynamicImportHandler__ = function (importer) { | ||
return `${window.app.cdnUrl.replace(/\/$/, '')}/${importer.replace( | ||
/^(\.\/)?/, | ||
'' | ||
)}`; | ||
}; | ||
window.__dynamicImportPreload__ = function (preloads) { | ||
return preloads.map( | ||
(preload) => `${window.app.cdnUrl.replace(/\/$/, '')}/${preload}` | ||
); | ||
}; |
There was a problem hiding this comment.
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__
.
); | ||
|
||
return ` | ||
<!DOCTYPE html> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Move to a separate HTML file.
// @preval | ||
/** | ||
* https://github.com/kentcdodds/babel-plugin-preval#preval-file-comment--preval | ||
* NOTE: This file is pre-evaluated during build time, using `babel-plugin-preval`. | ||
* This is ok as the loaded files are static anyway and it prevents possible | ||
* loading issues when files are required through Webpack own context. | ||
*/ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Trying to remember why we didn't do this but can't really. Maybe just cause preval wasn't really a thing back then.
transformIndexHtml(rawHtml, _ctx) { | ||
// Ensure to use the `cdnUrl` value when loading the entry point. | ||
// NOTE: with Webpack this is done by setting the `__webpack_public_path__`. | ||
const html = rawHtml.replace( | ||
new RegExp(`<script type="module"(.*) src="(.*)">`, 'g'), | ||
`<script type="module"$1 src="__CDN_URL__$2">` | ||
); | ||
|
||
return { | ||
html, | ||
tags: [ | ||
{ | ||
tag: 'script', | ||
// Inject the functions to dynamically change the public path. | ||
// This is also used for the `cdnUrl` and is the equivalent | ||
// of Webpack's `__webpack_public_path__`. | ||
children: htmlScripts.publicPath, | ||
injectTo: 'body', | ||
}, | ||
], | ||
}; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This transformer is important and it allows to prepend the asset URLs with the cdnUrl
value.
// TODO: allow to pass additional config options. | ||
// * `define` | ||
// * `plugins` |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This can be done as a follow up.
allowedHost: urls.localUrlForBrowser, | ||
contentBase: paths.appBuild, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Those weren't really used.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Super nice. Did a first review. Not much to add. Will however need another round with a fresh mind tomorrow.
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') | ||
); |
There was a problem hiding this comment.
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.
@@ -0,0 +1,72 @@ | |||
<!DOCTYPE html> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Agreed.
@@ -0,0 +1,11 @@ | |||
window.__dynamicImportHandler__ = function (importer) { |
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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 :)
// @preval | ||
/** | ||
* https://github.com/kentcdodds/babel-plugin-preval#preval-file-comment--preval | ||
* NOTE: This file is pre-evaluated during build time, using `babel-plugin-preval`. | ||
* This is ok as the loaded files are static anyway and it prevents possible | ||
* loading issues when files are required through Webpack own context. | ||
*/ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Trying to remember why we didn't do this but can't really. Maybe just cause preval wasn't really a thing back then.
TODOs:
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks again. Had a second look:
- I really like the addition of
preval
it makes a lot of sense - I wonder if we want to drop
pug
I don't see why we need it - We might use es6-template-strings - no direct benefit but avoids the
__
replacements while we're here
As a note: We don't use JavaScript modules as type="module"
yet. Support wise (not IE) we should. Still, it's to how I know and tell a change with Vite which might be worthwhile also documenting.
Lastly, I think the hardest part of understand in the vite setup is the asset and index.html re-routing but from what I can tell there is little we can do about it. I wonder just if it's fragile and could have bugs we don't know about yet.
packages/mc-dev-authentication/middlewares/create-mc-dev-authentication-middleware.js
Outdated
Show resolved
Hide resolved
const pug = require('pug'); | ||
const { logout } = require('../routes'); | ||
|
||
const compileLoginView = pug.compileFile( |
There was a problem hiding this comment.
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?
There was a problem hiding this comment.
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?
<!-- 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__ |
There was a problem hiding this comment.
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.
// Ensure to use the `cdnUrl` value when loading the entry point. | ||
// NOTE: with Webpack this is done by setting the `__webpack_public_path__`. | ||
const html = rawHtml.replace( | ||
new RegExp(`<script type="module"(.*) src="(.*)">`, 'g'), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I guess alternatively we could parse the HTML which might be more expensive. Maybe defining function prependCdnUrlToScriptSrc
would help. At least I got stuck here deducting that :)
Yeah that's kind of neat.
You mean mentioning (changelog, etc.) that it uses
Yes unfortunately there is no built-in support for this (yet). I thought about actually dropping support for the The alternative is to set the |
Yes. Just so people are aware. I don't think app-kit has a strict browser policy at least I am not aware of any. However, all existing script tags are not of
I think it makes sense to keep the status quo even if that means the internals of the commands are a bit wonky. As a later step we could discuss removing some of that functionality if possible if we want to simplify those internals then. |
Actually there is an issue with the setup for the So I'll have to rethink how to handle that 🧐 |
So it seems that this is more tricky than I thought. The good news is that there is a general consensus on supporting this feature (configuring the So for now, I would keep the setup simpler and avoid using the |
I think that's a reasonable restriction then until Vite supports it natively. |
…Url) and improve changeset
2ecc035
to
e2396e1
Compare
Alright, see changes in the last commit (e2396e1) with the fixes and improvements. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks. The simplification really makes it easier to follow. I think it's best to give it a shot also internally on small apps first and see how it behaves.
packages/mc-dev-authentication/middlewares/create-mc-dev-authentication-middleware.js
Show resolved
Hide resolved
console.log('Experimental Vite bundler enabled! 🚀'); | ||
console.warn( | ||
'NOTE that the "cdnURL" value is not supported at the moment when using Vite.' | ||
); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
💯
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🚀
(tech time work)
Background
The
mc-scripts
CLI uses Webpack as the bundler for development and for building the production assets.Webpack traditionally requires a lot of configuration and it's also not one of the fastest and more performant tools, especially in big projects. This usually results in a frustrating developer experience.
Proposal
Vite takes a different and more modern approach in bundling your application, primarily around new features like native ES modules.
Why Vite? Read here: https://vitejs.dev/guide/why.html
This PR adds opt-in support (by setting the environment variable
ENABLE_EXPERIMENTAL_VITE_BUNDLER="true"
) to switch the bundler used for developing and building production bundles.All the existing CLI commands fully work the same as before, so there is no migration step required from users to use the new bundle.
If you want to try it out, simply turn on the flag and enjoy 🚀
For comparison: build time seems to be cut in half on average (left with Webpack, right with Vite). 😎