Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
258 views
in Technique[技术] by (71.8m points)

javascript - Inlining ECMAScript Modules in HTML

I've been experimenting with new native ECMAScript module support that has recently been added to browsers. It's pleasant to finally be able import scripts directly and cleanly from JavaScript.

??? ?/example.html ??? ???
<script type="module">
  import {example} from '/example.js';

  example();
</script>
??? ?/example.js? ???
export function example() {
  document.body.appendChild(document.createTextNode("hello"));
};

However, this only allows me to import modules that are defined by separate external JavaScript files. I usually prefer to inline some scripts used for the initial rendering, so their requests don't block the rest of the page. With a traditional informally-structured library, that might look like this:

??? ?/inline-traditional.html ??? ???
<body>
<script>
  var example = {};

  example.example = function() {
    document.body.appendChild(document.createTextNode("hello"));
  };
</script>
<script>
  example.example();
</script>

However, naively inlining modules files obviously won't work, since it would remove the filename used to identify the module to other modules. HTTP/2 server push may be the canonical way to handle this situation, but it's still not an option in all environments.

Is it possible to perform an equivalent transformation with ECMAScript modules?

Is there any way for a <script type="module"> to import a module exported by another in the same document?


I imagine this could work by allowing the script to specify a file path, and behave as though it had already been downloaded or pushed from the path.

??? ?/inline-name.html ??? ???
<script type="module" name="/example.js">
  export function example() {
    document.body.appendChild(document.createTextNode("hello"));
  };
</script>

<script type="module">
  import {example} from '/example.js';

  example();
</script>

Or maybe by an entirely different reference scheme, such as is used for local SVG references:

??? ?/inline-id.html ??? ???
<script type="module" id="example">
  export function example() {
    document.body.appendChild(document.createTextNode("hello"));
  };
</script>
<script type="module">
  import {example} from '#example';

  example();
</script>

But neither of these hypotheticals actually work, and I haven't seen an alternative which does.

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

Hacking Together Our Own import from '#id'

Exports/imports between inline scripts aren't natively supported, but it was a fun exercise to hack together an implementation for my documents. Code-golfed down to a small block, I use it like this:

<script type="module" data-info="https://stackoverflow.com/a/43834063">let l,e,t
='script',p=/(froms+|imports+)['"](#[w-]+)['"]/g,x='textContent',d=document,
s,o;for(o of d.querySelectorAll(t+'[type=inline-module]'))l=d.createElement(t),o
.id?l.id=o.id:0,l.type='module',l[x]=o[x].replace(p,(u,a,z)=>(e=d.querySelector(
t+z+'[type=module][src]'))?a+`/* ${z} */'${e.src}'`:u),l.src=URL.createObjectURL
(new Blob([l[x]],{type:'application/java'+t})),o.replaceWith(l)//inline</script>

<script type="inline-module" id="utils">
  let n = 1;
  
  export const log = message => {
    const output = document.createElement('pre');
    output.textContent = `[${n++}] ${message}`;
    document.body.appendChild(output);
  };
</script>

<script type="inline-module" id="dogs">
  import {log} from '#utils';
  
  log("Exporting dog names.");
  
  export const names = ["Kayla", "Bentley", "Gilligan"];
</script>

<script type="inline-module">
  import {log} from '#utils';
  import {names as dogNames} from '#dogs';
  
  log(`Imported dog names: ${dogNames.join(", ")}.`);
</script>

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...