The import syntax translates this sentence into English.
ECMAScript 6's import
syntax has revolutionized JavaScript modularization, offering a clearer and more flexible approach to code organization. From static analysis to dynamic loading, this syntax supports various import/export patterns and has become a cornerstone of modern front-end development.
Basic Syntax of Static Import
Static imports are the core feature of the ES6 module system, determining dependencies at compile time. The basic syntax uses the import
keyword, followed by the bindings to import and the module path:
// Import all module contents
import * as utils from './utils.js';
// Import specific members
import { fetchData, processData } from './dataService.js';
// Import default export
import React from 'react';
Module paths can be relative (e.g., './module'
) or absolute (e.g., '/lib/module'
), but bare module names (e.g., 'lodash'
) are not directly supported—this requires bundler tools or Node.js's module resolution mechanism.
Named Imports and Exports
Named exports allow a module to expose multiple values, each with a specific identifier. The exporting side uses the export
keyword:
// mathUtils.js
export const PI = 3.1415926;
export function square(x) {
return x * x;
}
export class Vector2 {
constructor(x, y) {
this.x = x;
this.y = y;
}
}
The importing side can selectively import needed parts using destructuring syntax:
import { PI, square } from './mathUtils.js';
console.log(square(PI)); // Output: 9.869604
The as
keyword can rename imported bindings:
import { Vector2 as Vec2 } from './mathUtils.js';
const v = new Vec2(1, 2);
Default Exports and Imports
Each module can have one default export, typically used for the module's main functionality:
// logger.js
export default class Logger {
log(message) {
console.log(`[LOG] ${message}`);
}
}
When importing, curly braces are not needed, and any name can be used:
import MyLogger from './logger.js';
const logger = new MyLogger();
logger.log('Default import works');
Mixing default and named imports:
import React, { useState, useEffect } from 'react';
Dynamic Imports
ES2020 introduced dynamic import syntax import()
, which returns a Promise for on-demand loading:
button.addEventListener('click', async () => {
const module = await import('./dialogBox.js');
module.showDialog('Hello dynamic import!');
});
Dynamic imports are useful for:
- Code splitting at the route level
- Conditional module loading
- Reducing initial load size
Live Binding Feature of Imports
ES6 imports are live bindings—imported variables always reference the same memory address as exported variables:
// counter.js
export let count = 0;
export function increment() {
count++;
}
import { count, increment } from './counter.js';
console.log(count); // 0
increment();
console.log(count); // 1
This behavior differs from CommonJS's copying mechanism and requires attention when handling circular dependencies.
Re-exporting Syntax
In module re-exporting scenarios, compound syntax can be used:
// Re-export all named exports
export * from './mathUtils.js';
// Re-export specific named exports
export { PI as CircleRatio } from './mathUtils.js';
// Re-export default exports
export { default } from './logger.js';
Module Metadata
import.meta
provides module-related information, commonly import.meta.url
:
console.log(import.meta.url); // Outputs the full URL of the current module
Interoperability with CommonJS
In Node.js environments, ES modules can import CommonJS modules:
import fs from 'fs'; // Equivalent to const fs = require('fs')
import { readFile } from 'fs'; // Destructuring from CommonJS module
However, CommonJS modules cannot directly use require
to load ES modules—dynamic import()
must be used instead.
Usage in Browsers
Modern browsers natively support ES modules via <script type="module">
:
<script type="module">
import { render } from './app.js';
render(document.getElementById('root'));
</script>
Key considerations:
- Module scripts are deferred by default
- Server must support correct MIME types
- Cross-origin requests require CORS headers
Module Resolution Rules
Module resolution follows these rules:
- Full paths are loaded directly (e.g.,
'/lib/module.js'
) - Relative paths are resolved (e.g.,
'./module'
→'./module.js'
) - Bare module names rely on Node.js's
node_modules
lookup or bundler configuration
// File extensions can be omitted
import './styles.css'; // Requires loader configuration
Circular Dependency Handling
ES modules' live binding feature makes circular dependencies easier to manage:
// a.js
import { b } from './b.js';
export const a = 'A';
console.log(b); // Output: B
// b.js
import { a } from './a.js';
export const b = 'B';
console.log(a); // Output: undefined (a not yet initialized)
Advantages of Static Analysis
The static nature of import
syntax offers several benefits:
- Early detection of reference errors
- Support for tree-shaking optimizations
- Deterministic dependency graphs
- Better IDE support
Module Loading Process
The complete module loading process includes:
- Resolution: Determining the absolute module path
- Fetching: Downloading the module file
- Instantiation: Linking imports and exports
- Evaluation: Executing the module code
Import Assertions
ES2022 introduced import assertions for specifying module types:
import jsonData from './data.json' assert { type: 'json' };
Currently, JSON module assertions are widely supported, with potential extensions to other types in the future.
Module Organization Patterns
Common module organization patterns:
// Unified entry pattern
// components/index.js
export { default as Button } from './Button.js';
export { default as Input } from './Input.js';
// Feature aggregation pattern
// dataAccess.js
export * as users from './users.js';
export * as products from './products.js';
Performance Optimization Techniques
Optimization strategies based on import
:
- Code splitting: Using dynamic imports to split bundles
- Preloading: Using
<link rel="modulepreload">
- Parallel loading: Optimal request scheduling via static analysis
<link rel="modulepreload" href="./critical-module.js">
Toolchain Support
Modern tooling support for ES modules:
- Webpack: Outputs ES modules via
output.module
- Rollup: Natively supports ES module bundling
- Babel: Transforms
import
syntax for target environments - Node.js:
.mjs
extension orpackage.json
'stype
field
Comparison with Historical Module Systems
Differences between module systems:
Feature | ES Modules | CommonJS | AMD |
---|---|---|---|
Loading | Static | Dynamic | Dynamic |
Binding | Live | Copy | Implementation-dependent |
Top-level this |
undefined | module | undefined |
Circular Deps | Supported | Limited | Supported |
Solutions to Common Issues
Examples of handling typical problems:
- Incorrect import paths:
// Error: Missing file extension or wrong path
import { util } from './util'; // May fail
// Correct:
import { util } from './util.js';
- Browser CORS restrictions:
// Server must configure Access-Control-Allow-Origin
import { api } from 'https://other-domain.com/module.js';
- Default export confusion:
// Exporting side
export default function() {}
// Incorrect import:
import { default } from './module'; // Error!
// Correct import:
import anonymousFn from './module';
Future Directions
The evolution of ECMAScript modules includes:
- Import maps: Controlling bare module name resolution
- JSON modules: Native support without assertions
- CSS modules: Proposals for native CSS imports
- Finer-grained dependency management
<!-- Import maps example -->
<script type="importmap">
{
"imports": {
"lodash": "/node_modules/lodash-es/lodash.js"
}
}
</script>
本站部分内容来自互联网,一切版权均归源网站或源作者所有。
如果侵犯了你的权益请来信告知我们删除。邮箱:cc@cccx.cn
下一篇:模块的异步加载