阿里云主机折上折
  • 微信号
Current Site:Index > The execution process of native ESM in the browser

The execution process of native ESM in the browser

Author:Chuan Chen 阅读数:31566人阅读 分类: 构建工具

Basic Concepts of Native ESM in Browsers

Native ESM (ECMAScript Modules) is a JavaScript module system supported by modern browsers. Unlike traditional script loading methods, ESM allows developers to organize code in a modular way, explicitly specifying dependencies. Browsers recognize and process ES modules through the <script type="module"> tag.

<script type="module">
  import { foo } from './module.js';
  console.log(foo); // 'bar'
</script>

Module Resolution and Loading Process

When a browser encounters a script with type="module", it initiates the following processing flow:

  1. Parsing Phase: The browser parses the HTML document and does not immediately execute module scripts but first performs parsing.
  2. Dependency Graph Construction: Starting from the entry module, it recursively analyzes all import statements to build a complete module dependency graph.
  3. Fetching Phase: It initiates network requests to fetch module files in the order of dependencies.
  4. Parsing and Linking: Each module is parsed, and reference relationships between modules are established.
  5. Execution Phase: Module code is executed in the topological order of the dependency graph.
// moduleA.js
import { b } from './moduleB.js';
export const a = 'a' + b;

// moduleB.js
export const b = 'b';

Module Identifier Resolution

Browsers follow strict URL resolution rules when processing ESM imports:

  • Relative paths must include file extensions (e.g., ./module.js).
  • Absolute paths and URLs can be used directly.
  • Bare module specifiers (e.g., import 'lodash') will cause errors without using a bundler.
// Valid imports
import './lib/utils.js';
import { Component } from 'https://unpkg.com/vue@3/dist/vue.esm-browser.js';

// Invalid imports (will throw errors in native ESM)
import utils from './utils';
import { cloneDeep } from 'lodash';

Module Execution Characteristics

ESM execution in browsers has the following key features:

  1. Automatic Strict Mode: Module code executes in strict mode by default.
  2. Top-Level Scope Isolation: Variables in modules do not leak into the global scope.
  3. Singleton Pattern: Modules with the same URL are loaded and executed only once.
  4. Deferred Execution: Module scripts inherently have the defer attribute and execute in order after the document is parsed.
// module.js
// The following code works in modules but would throw errors in traditional scripts
export const foo = 'bar';
const privateVar = 'secret'; // Does not pollute the global scope

// Automatic strict mode
delete Object.prototype; // Throws TypeError

Dynamic Imports

Browsers support the import() dynamic import syntax, which returns a Promise:

// Load modules on demand
button.addEventListener('click', async () => {
  const module = await import('./dialog.js');
  module.openDialog();
});

Dynamic imports are suitable for:

  • Code splitting at the route level.
  • Conditionally loading different modules.
  • Reducing initial load time.

Module Preloading

Use <link rel="modulepreload"> to preload modules and their dependencies:

<link rel="modulepreload" href="critical-module.js">

Preloading optimization strategies:

  1. Identify modules in the critical rendering path.
  2. Preload deep dependencies.
  3. Use it in conjunction with HTTP/2 server push.

Relationship with Vite

Vite leverages native ESM for fast development server startup:

  1. Development Environment: Directly serves source code in ESM format.
  2. Dependency Handling: Pre-bundles third-party packages into ESM format.
  3. On-Demand Compilation: Only compiles the currently requested file.
// Special URLs processed by Vite
import { createApp } from '/@modules/vue.js'; // Rewritten bare module imports

Performance Optimization Considerations

Performance issues to note when using native ESM:

  1. Deep Dependency Chains: Excessive nested imports can lead to waterfall loading.
  2. Small File Problem: Numerous small modules increase HTTP request overhead.
  3. Caching Strategy: Set appropriate Cache-Control headers.

Optimization example:

<!-- Use bundles to reduce the number of requests -->
<script type="module" src="bundle.js"></script>

<!-- Provide a nomodule fallback for browsers that don't support ESM -->
<script nomodule src="legacy-bundle.js"></script>

Browser Compatibility Handling

Handling older browsers that don't support ESM:

  1. nomodule Attribute: Provide fallback scripts for browsers that don't support modules.
  2. Build-Time Downgrading: Use tools to generate ES5-compatible code.
  3. Feature Detection: Dynamically decide which version of the code to load.
<script type="module" src="modern.js"></script>
<script nomodule src="legacy.js"></script>

Practical Application Example

A complete ESM application structure example:

<!-- index.html -->
<!DOCTYPE html>
<html>
<head>
  <title>ESM App</title>
  <link rel="modulepreload" href="/src/main.js">
</head>
<body>
  <script type="module" src="/src/main.js"></script>
</body>
</html>
// src/main.js
import { createApp } from 'vue';
import App from './App.vue';

createApp(App).mount('#app');

Debugging and Troubleshooting

Browser developer tools provide ESM debugging support:

  1. Sources Panel: View loaded module files.
  2. Network Panel: Analyze module loading waterfall charts.
  3. Console Warnings: Identify invalid module specifiers.

Common issue handling:

  • Check if file extensions are complete.
  • Ensure the server correctly sets MIME types.
  • Verify Cross-Origin Resource Sharing (CORS) configurations.

Security Considerations

Security considerations with ESM:

  1. CORS Restrictions: Module scripts must pass CORS checks.
  2. Credential Control: Cross-origin requests do not send cookies by default.
  3. Content Security Policy: Appropriate CSP settings are required.
<!-- Correct CORS headers are needed -->
<script type="module" src="https://other-origin.com/module.js"></script>

本站部分内容来自互联网,一切版权均归源网站或源作者所有。

如果侵犯了你的权益请来信告知我们删除。邮箱:cc@cccx.cn

Front End Chuan

Front End Chuan, Chen Chuan's Code Teahouse 🍵, specializing in exorcising all kinds of stubborn bugs 💻. Daily serving baldness-warning-level development insights 🛠️, with a bonus of one-liners that'll make you laugh for ten years 🐟. Occasionally drops pixel-perfect romance brewed in a coffee cup ☕.