Inlining ECMAScript Modules in HTML

前端 未结 3 1927
情话喂你
情话喂你 2020-12-07 20:51

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 cl

3条回答
  •  一个人的身影
    2020-12-07 21:33

    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:

    
    
    
    
    
    
    

    Instead of

    The execution of module script elements is always deferred until after the document is parsed, so we don't need to worry about trying to support the way that traditional script elements can modify the document while it's still being parsed.

    export {};
    
    for (const original of document.querySelectorAll('script[type=inline-module]')) {
      const replacement = document.createElement('script');
    
      // Preserve the ID so the element can be selected for import.
      if (original.id) {
        replacement.id = original.id;
      }
    
      replacement.type = 'module';
    
      const transformedSource = original.textContent.replace(
        // Find anything that looks like an import from '#some-id'.
        /(from\s+|import\s+)['"](#[\w\-]+)['"]/g,
        (unmodified, action, selector) => {
          // If we can find a suitable script with that id...
          const refEl = document.querySelector('script[type=module][src]' + selector);
          return refEl ?
            // ..then update the import to use that script's src URL instead.
            `${action}/* ${selector} */ '${refEl.src}'` :
            unmodified;
        });
    
      // Include the updated code in the src attribute as a blob URL that can be re-imported.
      replacement.src = URL.createObjectURL(
        new Blob([transformedSource], {type: 'application/javascript'}));
    
      // Insert the updated code inline, for debugging (it will be ignored).
      replacement.textContent = transformedSource;
    
      original.replaceWith(replacement);
    }
    

    Warnings: this simple implementation doesn't handle script elements added after the initial document has been parsed, or allow script elements to import from other script elements that occur after them in the document. If you have both module and inline-module script elements in a document, their relative execution order may not be correct. The source code transformation is performed using a crude regex that won't handle some edge cases such as periods in IDs.

提交回复
热议问题