I'd like to make a Javascript file that
export
s its content (eg a class) if it can export
(eg it has been loaded with <script type="module">
) window
and global
. For example, let's assume such a file print.js
.
One can use it like:
<script type="module">
import print_things from "./print.js";
print_things("Javascript innovation");
</script>
or,
<script src="./print.js"></script>
<script>
print_things("Hmmmmmmm.");
</script>
Currently, using export
makes the script throw an error in Case B : Uncaught SyntaxError: Unexpected token export
. So it has to know whether export
is available on the environment whereon it runs, in order to support the both use cases. How do I do this?
Check out UMD (universal module definition). Namely, this example
(function (root, factory) {
if (typeof define === 'function' && define.amd) {
// AMD. Register as an anonymous module.
define(['exports', 'b'], function (exports, b) {
factory((root.commonJsStrictGlobal = exports), b);
});
} else if (typeof exports === 'object' && typeof exports.nodeName !== 'string') {
// CommonJS
factory(exports, require('b'));
} else {
// Browser globals
factory((root.commonJsStrictGlobal = {}), root.b);
}
}(typeof self !== 'undefined' ? self : this, function (exports, b) {
// Use b in some fashion.
// attach properties to the exports object to define
// the exported module properties.
exports.action = function () {};
}));
Browsers that understand type=module
should ignore scripts with a nomodule
attribute. This means you can serve a module tree to module-supporting browsers while providing a fall-back to other browsers.
<script type="module" src="module.js"></script>
<script nomodule src="fallback.js"></script>
( Note: you probably shouldn't use this in the real world , but it is totally valid and does exactly what you want.)
Here's an implementation of your print.js
:
function print_things(msg) {
console.log(msg)
}
if(0)typeof await/2//2; export default print_things
<script type=module> // (renamed to avoid name collision) import print_things2 from "https://12Me21.github.io/external/print.js" print_things2("Javascript innovation") </script> <script src="https://12Me21.github.io/external/print.js"></script> <script> print_things("Hmmmmmmm.") </script>
await/2//2; ...
await/2//2; ...
is parsed differently depending on context:
await
(operator) /2/
(regexp) /
(divide) 2
(number) await
(variable) /
(divide) 2
(number) //2 ...
( comment ) When it's parsed as a comment, the rest of the line is ignored. So, the export
statement is only visible to module scripts.
Here is the relevant part of the specification: 15.8 Async Function Definitions > Syntax > AwaitExpression > Note 1
As a non-module script, it should work in any browser (even ancient versions of Internet Explorer etc.), and is still valid with "use strict"
enabled
However, loading it as a module requires support for "top-level await", which was added a few years after modules themselves (~2021 vs ~2018), so keep that in mind.
(It also works with nodejs, in either mode)
I've used this trick in a library that I wrote, and it's been working fine in multiple environments for several months. However, it has caused some problems with external tools (frameworks, compilers, minifiers, etc.)
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.