handlebars.js
handlebars.js copied to clipboard
Support for ES6 Modules
Is there a timescale for Handlebars supporting ES6 modules?
This would allow it to be imported into JS modules without needing to add it to the html page head as a UMD module.
Cheers.
Related to #1707, #1696.
Hi @jaylinski, I've seen that both these referenced issues have been resolved but no new release made yet. Is there a rough ETA for ES6 support? Just curious, no pressure :)
Theoretically, there should be a way to add an additional grunt task under "webpack" option to utilize the experimental "module" library type:
https://webpack.js.org/configuration/output/#type-module
I'm experimenting with some options but haven't found the right way to synthesize the configurations yet. But all you really need is to replace the UMD header with a simple "export default" followed by the factory closure and invocation. I'll report with (hopefully) an MR if I find something that works; unfortunately my Grunt and Webpack knowledge are minimal, so no guarantees.
@Tythos I'd rather replace our outdated grunt/webpack v1 build with a new rollup or https://github.com/developit/microbundle build. But for our 4.x branch, a solution like yours may fit better.
Understood. With the webpack major version breaking (currently "^1.12.6", whereas the module feature remains experimental even in 5+), it's probably not an option anyway just for this feature. Instead, I just added a non-umd build output (which gets the "var Handlebars = {...closure}" treatment) that was then appended with "export default Handlebars". It's manual and dirty for now, but it does work very well and I've captured it in a gist for easy submodule-inclusion.
+1 would love handlebars to support ES6 modules as well :)
@Tythos
I just added a non-umd build output (which gets the "var Handlebars = {...closure}" treatment) that was then appended with "export default Handlebars"
Can you please elaborate on this? What options did you use when precompiling your templates? I'm struggling getting them working with converting my codebase to modules.
Here is my solution:
diff --git a/node_modules/handlebars/bin/handlebars b/node_modules/handlebars/bin/handlebars
index 7749121..878a36c 100755
--- a/node_modules/handlebars/bin/handlebars
+++ b/node_modules/handlebars/bin/handlebars
@@ -15,6 +15,11 @@ var argv = parseArgs({
'description': 'Exports amd style (require.js)',
'alias': 'amd'
},
+ 'esm': {
+ 'type': 'string',
+ 'description': 'Exports ECMAScript module style, path to Handlebars module (eg. "handlebars/lib/handlebars")',
+ 'default': null
+ },
'c': {
'type': 'string',
'description': 'Exports CommonJS style, path to Handlebars module',
diff --git a/node_modules/handlebars/dist/cjs/precompiler.js b/node_modules/handlebars/dist/cjs/precompiler.js
index 9e6cd63..0989921 100644
--- a/node_modules/handlebars/dist/cjs/precompiler.js
+++ b/node_modules/handlebars/dist/cjs/precompiler.js
@@ -180,7 +180,7 @@ module.exports.cli = function (opts) {
}
// Force simple mode if we have only one template and it's unnamed.
- if (!opts.amd && !opts.commonjs && opts.templates.length === 1 && !opts.templates[0].name) {
+ if (!opts.amd && !opts.commonjs && !opts.esm && opts.templates.length === 1 && !opts.templates[0].name) {
opts.simple = true;
}
@@ -203,6 +203,8 @@ module.exports.cli = function (opts) {
output.add("define(['" + opts.handlebarPath + 'handlebars.runtime\'], function(Handlebars) {\n Handlebars = Handlebars["default"];');
} else if (opts.commonjs) {
output.add('var Handlebars = require("' + opts.commonjs + '");');
+ } else if (opts.esm) {
+ output.add(`import Handlebars from "${opts.esm}";`);
} else {
output.add('(function() {\n');
}
@@ -258,7 +260,9 @@ module.exports.cli = function (opts) {
output.add(['return ', objectName, ';\n']);
}
output.add('});');
- } else if (!opts.commonjs) {
+ } else if (opts.esm) {
+ output.add(`export default Handlebars;`);
+ } else if (!opts.commonjs && !opts.esm) {
output.add('})();');
}
}
Partially from #1816, partially from @Tythos's comment.
I'm using patch-package to run this patch.
npm install patch-package
"scripts": {
"hbs": "handlebars .build/hbs/**.* -f dist/hbsTemplates.js --esm handlebars",
"postinstall": "patch-package"
}
The only problem I have now is that for some reason I'm unable to use import Handlebars from "handlebars/runtime", so I'm importing from "handlebars" and it seems like it's working
In addition to "handlebars" and "runtime" entries under the "webpack" field in "Gruntfile.js", I added another build definition:
esm: {
entry: './dist/cjs/handlebars.js',
output: {
filename: 'handlebars.mjs',
libraryTarget: 'var'
},
}
With webpack v1 (e.g., before "module" support), this generates a "handlebars.mjs" file within the "dist/" folder. In place of a UMD header, this assigns the closure return to a "var Handlebars = " expression. This can easily be replaced directly with an "export default" instead, or you can append "export default Handlebars;" to the end of the file.
That having been said, the patch above is much more comprehensive.
Is there a rough ETA for this getting released? This would be helpful for us.
Happy to help if there is something pending here.
Edit: Our usecase seems to have gotten resolved post v4.7.8 release. (Our usecase may not have needed es6 support)
Thanks for your patch @Sparticuz !
The only problem I have now is that for some reason I'm unable to use
import Handlebars from "handlebars/runtime"
Importing handlebars like this seems to work:
import Handlebars from "handlebars/lib/handlebars.runtime";
Would
import * as Handlebars from "handlebars";
make the trick?
This would also be helpful for us, is there a rough ETA?