mde / ejs

Embedded JavaScript templates -- http://ejs.co
Apache License 2.0
7.71k stars 846 forks source link

EJS as a browser ES6 module to import() #653

Closed mercmobily closed 2 years ago

mercmobily commented 2 years ago

I am working on a huge web application, and we have a big push for avoiding the pollution of the global scope, and use ES6 import instead. This is on the CLIENT side -- the server side is always happy with require(), and by the looks of it things will stay that way for the foreseeable future.

Ar you planning in making this possible:

import `ejs` from `ejs.js`;

...? I realise it's not straightforward. I can see that to make the browser version of it you are using browserify, which had its last real commit nearly 2 years ago and will pollute the global scope.

Can I humbly ask if there are any plans to provide the module as an ES6 import, so that it can be used as explained above?

mde commented 2 years ago

I have no plans currently to implement this myself, but I would certainly entertain a PR that does. I'm going to close this Issue for now. Feel free to reopen if there is a PR for this to look at.

mercmobily commented 2 years ago

Matthew, I am very happy to provide a PR for this. But, can we discuss strategies first? There are several ways to do it, and none of them are really pretty, to be honest.

Do you have any gut preferences?

A few options:

Please let me know. I lean towards the second solution, at least for now.

mercmobily commented 2 years ago

I have two more questions.

(1) The module uses the node IO library fs (expecially includeFile()). Is it assumed that includeFile just won't work when used in the browser? (the module uses path, but that's shimmed by browserify.

(2) I tried to build it.

merc@merc-All-Series:~/Development/ejs.MOBILYENTERPRISES$ ./node_modules/jake/bin/cli.js  build
Starting 'clobberPackage'...
Finished 'clobberPackage' after 1 ms
Starting 'clobber'...
Finished 'clobber' after 0 ms
Starting 'clean'...
Cleaned up compiled files.
Finished 'clean' after 1 ms
Starting 'lint'...
Linting completed.
Finished 'lint' after 733 ms
Starting 'browserify'...
Browserification completed.
Finished 'browserify' after 192 ms
Starting 'minify'...
Parse error at ejs.js:606,28
            throw new Error(`destructuredLocals[${i}] is not a valid JS identifi
                            ^
ERROR: Unexpected character '`'
    at JS_Parse_Error.get (eval at <anonymous> (/home/merc/Development/ejs.MOBILYENTERPRISES/node_modules/uglify-js/tools/node.js:20:1), <anonymous>:69:23)
    at fatal (/home/merc/Development/ejs.MOBILYENTERPRISES/node_modules/uglify-js/bin/uglifyjs:298:27)
    at run (/home/merc/Development/ejs.MOBILYENTERPRISES/node_modules/uglify-js/bin/uglifyjs:241:9)
    at Object.<anonymous> (/home/merc/Development/ejs.MOBILYENTERPRISES/node_modules/uglify-js/bin/uglifyjs:167:5)
    at Module._compile (internal/modules/cjs/loader.js:999:30)
    at Object.Module._extensions..js (internal/modules/cjs/loader.js:1027:10)
    at Module.load (internal/modules/cjs/loader.js:863:32)
    at Function.Module._load (internal/modules/cjs/loader.js:708:14)
    at Function.executeUserEntryPoint [as runMain] (internal/modules/run_main.js:60:12)
    at internal/main/run_main_module.js:17:47
jake aborted.
Error: Command failed: node_modules/uglify-js/bin/uglifyjs ejs.js > ejs.min.js
    at checkExecSyncError (child_process.js:635:11)
    at execSync (child_process.js:671:15)
    at exec (/home/merc/Development/ejs.MOBILYENTERPRISES/jakefile.js:5:3)
    at Task.action (/home/merc/Development/ejs.MOBILYENTERPRISES/jakefile.js:36:3)
    at Task.run (/home/merc/Development/ejs.MOBILYENTERPRISES/node_modules/jake/lib/task/task.js:314:29)
    at processImmediate (internal/timers.js:461:21)
mercmobily commented 2 years ago

I don't mean to pester, just checking you are getting these updates now that the issue is closed!

mde commented 2 years ago

Yes, I am getting these updates. Unfortunately neither of those options seem super appealing. As for option one — I have zero interest in using TypeScript for EJS. I have used it, and cannot overstate how much I dislike it. And for option two — adding yet a new build step, with a different target (ES6) would require non-trivial ongoing maintenance. Once you add something, it has to keep working pretty much forever. I'm not opposed to the idea in theory, but would really like to do it in a way that doesn't add significantly to the maintenance-required surface area of the project.