JavaScript筆記之import和require的區(qū)別與對(duì)比
前言
在 JavaScript 中,import 和 require 都用于引入模塊,但它們來(lái)自不同的模塊規(guī)范,在語(yǔ)法、加載時(shí)機(jī)、作用域、生態(tài)支持等方面差異很大。
1.模塊系統(tǒng)不同
require- CommonJS 規(guī)范
// Node.js 最早的模塊系統(tǒng)(服務(wù)器端)
const fs = require('fs');
const _ = require('lodash');
import- ES6 模塊規(guī)范
// 瀏覽器/現(xiàn)代 Node.js 環(huán)境
import fs from 'fs'; // 默認(rèn)導(dǎo)入
import { readFile } from 'fs'; // 命名導(dǎo)入
import * as fsModule from 'fs'; // 全部導(dǎo)入
| 規(guī)范 | 代表 | 出現(xiàn)背景 |
|---|---|---|
| CommonJS | require | Node.js 最早的模塊系統(tǒng)(服務(wù)器端) |
| ES Module(ESM) | import | ECMAScript 官方標(biāo)準(zhǔn)(瀏覽器 & Node) |
?? 核心結(jié)論:
require是 運(yùn)行時(shí)模塊加載機(jī)制,import是 編譯期模塊聲明機(jī)制。
2.加載時(shí)機(jī)與特性對(duì)比
require:運(yùn)行時(shí)加載
const moduleA = require('./a') // 執(zhí)行到這里才加載
特點(diǎn):
- 同步加載
- 執(zhí)行順序 = 代碼執(zhí)行順序
- 可條件、可動(dòng)態(tài)
import:編譯時(shí)加載(靜態(tài)分析)
import moduleA from './a'
特點(diǎn):
- 在代碼執(zhí)行前就確定依賴關(guān)系
- 可被 bundler / JS 引擎優(yōu)化
- 支持 Tree Shaking
?? 這是 Vite / Rollup / Webpack 能做 Tree Shaking 的根本原因
| 特性 | require (CommonJS) | import (ES6) |
|---|---|---|
| 加載時(shí)機(jī) | 運(yùn)行時(shí)同步加載 | 編譯時(shí)靜態(tài)分析 |
| 位置要求 | 可在代碼任意位置 | 必須位于模塊頂部(除動(dòng)態(tài)導(dǎo)入) |
| 靜態(tài)分析 | 不支持 Tree Shaking | 支持 Tree Shaking |
| 異步支持 | 同步加載 | 靜態(tài)導(dǎo)入同步,動(dòng)態(tài)導(dǎo)入異步 |
| 懶加載 | 需配合特定語(yǔ)法 | 原生支持 import() 懶加載 |
import 只能寫在頂層
? 說(shuō)的是:import x from 'y'import() 可以寫在任何地方
? 它是一個(gè)返回 Promise 的函數(shù)調(diào)用
3.懶加載實(shí)現(xiàn)方式對(duì)比
require的懶加載(Webpack 特定)
// 方式1:require.ensure (Webpack 特定)
const Home = resolve => {
require.ensure(['./views/Home.vue'], () => {
resolve(require('./views/Home.vue'));
});
};
// 方式2:動(dòng)態(tài) require (Webpack)
const About = () => {
return new Promise(resolve => {
require(['./views/About.vue'], resolve);
});
};
import的懶加載(ES6 標(biāo)準(zhǔn))
// 標(biāo)準(zhǔn) ES6 動(dòng)態(tài)導(dǎo)入
const Home = () => import('./views/Home.vue');
// 更復(fù)雜的懶加載配置
const UserProfile = () => ({
component: import('./UserProfile.vue'),
loading: LoadingComponent,
delay: 200,
timeout: 3000
});
4.實(shí)際打包效果
require的打包
示例 :require
// main.js
const utils = require('./utils')
utils.a()
打包結(jié)果(簡(jiǎn)化)
function a() {}
function b() {}
const utils = { a, b }
utils.a()
?? 結(jié)論:
?? require 整包引入,無(wú)法安全刪除 b
import的打包
示例 :靜態(tài) import
// utils.js
export function a() {}
export function b() {}
// main.js
import { a } from './utils'
a()
打包結(jié)果(簡(jiǎn)化)
function a() {}
// b 被刪除(Tree Shaking)
a()
?? 結(jié)論:
?? import 能在打包階段精準(zhǔn)刪除未使用代碼。
5、代碼拆包(code splitting)差異
import(動(dòng)態(tài))
import('./About.vue')
打包結(jié)果(Webpack / Vite):
// 主 bundle
function loadAbout() {
return __loadChunk__('about').then(...)
}
// about.chunk.js(獨(dú)立) export default About
?? 天然支持拆包
require(動(dòng)態(tài))
require('./About.vue')
?? 結(jié)果:
- Webpack:只能整體打包進(jìn)主 bundle
- Rollup / Vite:直接報(bào)錯(cuò)或不支持
?? 無(wú)法可靠拆包
6、運(yùn)行時(shí)代碼結(jié)構(gòu)差異(很重要)
require 打包后(CommonJS Runtime)
(function(modules) {
function __webpack_require__(id) {
// 同步加載
}
})(modules)
特點(diǎn):
- 同步執(zhí)行
- module.exports
- 需要模擬 CommonJS 環(huán)境
import 打包后(ESM Runtime)
Webpack(轉(zhuǎn)換后)
__webpack_require__.d(exports, {
a: () => a
})
Vite(生產(chǎn))
import { a } from './chunk.js'
特點(diǎn):
- 支持 live binding
- 更貼近瀏覽器原生模塊
- 運(yùn)行時(shí)代碼更少
Vite 項(xiàng)目里的一個(gè)“隱形差異”(很重要)
Vite 的策略
- 開發(fā)環(huán)境:原生 ESM(幾乎不打包)
- 生產(chǎn)環(huán)境:Rollup 打包
結(jié)果:
import { debounce } from 'lodash-es'
?? 只打進(jìn) debounce
const _ = require('lodash')
?? 整個(gè) lodash 被打包
包體積 & 性能對(duì)比(真實(shí)工程影響)
| 維度 | import | require |
|---|---|---|
| 主包體積 | 更小 | 更大 |
| Tree Shaking | ? | ? |
| 懶加載 | ?(import()) | ? |
| 執(zhí)行效率 | 更優(yōu) | 較差 |
| 構(gòu)建器優(yōu)化 | 極佳 | 受限 |
?? 在大型 Vue 項(xiàng)目里,差距可能是 幾十 KB ~ 數(shù)百 KB
7.現(xiàn)代項(xiàng)目中的使用場(chǎng)景
Node.js 項(xiàng)目
// ES6 模塊(Node.js 13+,package.json 中 type: "module")
import express from 'express';
import { createServer } from 'http';
// 或者 CommonJS(傳統(tǒng))
const express = require('express');
const http = require('http');
Vue/React 項(xiàng)目
// Vue Router 懶加載(推薦)
const router = new VueRouter({
routes: [
{
path: '/dashboard',
component: () => import('./views/Dashboard.vue') // ES6 import
}
]
});
// React 懶加載
const Dashboard = React.lazy(() => import('./components/Dashboard'));
混合使用(不推薦但可能遇到)
// 在 ES6 模塊中導(dǎo)入 CommonJS 模塊
import _ from 'lodash'; // lodash 是 CommonJS 模塊
// 在 CommonJS 模塊中導(dǎo)入 ES6 模塊(Node.js)
const fs = require('fs');
const es6Module = await import('./es6-module.mjs'); // 需要異步
// Webpack 環(huán)境中可以混合
const oldModule = require('./old-module.js'); // CommonJS
const newModule = import('./new-module.js'); // ES6
8.性能對(duì)比
// 測(cè)試示例:加載 10 個(gè)模塊
const modules = ['module1', 'module2', 'module3'];
// require - 同步,阻塞執(zhí)行
console.time('require');
modules.forEach(name => {
const module = require(`./${name}.js`);
});
console.timeEnd('require');
// import - 異步,非阻塞
console.time('import');
const promises = modules.map(name => import(`./${name}.js`));
await Promise.all(promises);
console.timeEnd('import');
9.Tree Shaking 差異
import支持靜態(tài)分析
// 只導(dǎo)入需要的部分,打包時(shí)未使用的代碼會(huì)被移除
import { Button, Input } from 'antd'; // Tree Shaking 生效
import 'antd/dist/antd.css';
// 動(dòng)態(tài)導(dǎo)入也支持 Tree Shaking
const { Modal } = await import('antd');
為什么import能 Tree Shaking?
import { a } from './utils'
構(gòu)建器在 編譯階段 就知道:
- 引入了哪個(gè)模塊
- 使用了哪個(gè)導(dǎo)出
- 依賴關(guān)系是 靜態(tài)確定的
require不支持 Tree Shaking
// 整個(gè)模塊都會(huì)被加載
const antd = require('antd'); // 整個(gè) antd 包都會(huì)被包含
const Button = antd.Button;
為什么require不行?
const mod = require('./' + name)
構(gòu)建器 無(wú)法確定:
- 到底 require 哪個(gè)文件
- require 的返回結(jié)構(gòu)
- 是否有副作用
?? 只能保守處理:全留
10.總結(jié)選擇建議
| 場(chǎng)景 | 推薦使用 | 原因 |
|---|---|---|
| 現(xiàn)代前端項(xiàng)目 | import | ES6 標(biāo)準(zhǔn),支持 Tree Shaking,更好的懶加載 |
| Node.js 新項(xiàng)目 | import (ES6 模塊) | 官方推薦,更好的異步支持 |
| Node.js 舊項(xiàng)目 | require | 保持兼容性 |
| 路由懶加載 | import() | 語(yǔ)法簡(jiǎn)潔,標(biāo)準(zhǔn)支持 |
| 條件加載 | import() | 異步,可配合條件判斷 |
| 需要同步加載 | require 或靜態(tài) import | 立即需要模塊時(shí) |
11.最佳實(shí)踐示例
// 1. 主應(yīng)用使用靜態(tài)導(dǎo)入
import Vue from 'vue';
import Router from 'vue-router';
// 2. 路由使用動(dòng)態(tài)導(dǎo)入懶加載
const routes = [
{
path: '/',
component: () => import('./views/Home.vue')
},
{
path: '/about',
component: () => import('./views/About.vue')
}
];
// 3. 條件加載(按需加載)
if (user.needsAdminPanel) {
const AdminPanel = await import('./admin/AdminPanel.vue');
}
// 4. 預(yù)加載(提高用戶體驗(yàn))
const preloadModules = [
import('./views/Products.vue'), // 預(yù)加載可能訪問(wèn)的頁(yè)面
import('./views/Contact.vue')
];
核心結(jié)論:
- 現(xiàn)代前端開發(fā)優(yōu)先使用 import/export
- 懶加載使用動(dòng)態(tài) import()
- require 主要用于古早 Node.js 傳統(tǒng)項(xiàng)目或兼容性需求
總結(jié)
到此這篇關(guān)于JavaScript筆記之import和require區(qū)別與對(duì)比的文章就介紹到這了,更多相關(guān)JS import和require區(qū)別與對(duì)比內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
- 一文讓你徹底搞清楚javascript中的require、import與export
- 一文帶你搞懂JS中導(dǎo)入模塊import和require的區(qū)別
- JavaScript中使用import 和require打包后實(shí)現(xiàn)原理分析
- JavaScript中require和import的區(qū)別詳解
- JS中Require與Import 區(qū)別對(duì)比分析
- Js模塊打包exports require import的用法和區(qū)別
- js中關(guān)于require與import的區(qū)別及說(shuō)明
- JavaScript中require和import有何區(qū)別詳解
相關(guān)文章
w3c聲明下可運(yùn)行 兼容性比較好的js對(duì)聯(lián)廣告集合
最近有美工朋友找我們要兼容性比較好的對(duì)聯(lián)廣告代碼,我們給他一個(gè)他竟然不能運(yùn)行,經(jīng)過(guò)排查,這是因?yàn)楝F(xiàn)在的廣告也用了一樣代碼,函數(shù)命名重復(fù)。2011-07-07
微信小程序如何在頁(yè)面跳轉(zhuǎn)時(shí)進(jìn)行頁(yè)面導(dǎo)航
小程序能夠在不同的頁(yè)面進(jìn)行跳轉(zhuǎn)切換,路由起到了至關(guān)重要的作用,下面這篇文章主要給大家介紹了關(guān)于微信小程序如何在頁(yè)面跳轉(zhuǎn)時(shí)進(jìn)行頁(yè)面導(dǎo)航的相關(guān)資料,需要的朋友可以參考下2022-09-09
JavaScript對(duì)象創(chuàng)建的七種方式詳解
作為一名前端開發(fā)者,JavaScript中對(duì)象創(chuàng)建是很重要,在JavaScript這門基于原型的語(yǔ)言中,對(duì)象幾乎無(wú)處不在,本文我將帶領(lǐng)大家回顧JavaScript對(duì)象創(chuàng)建的7種方式,需要的朋友可以參考下2025-09-09
js實(shí)現(xiàn)ajax的用戶簡(jiǎn)單登入功能
這篇文章主要為大家詳細(xì)介紹了js實(shí)現(xiàn)ajax的用戶簡(jiǎn)單登入功能,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2020-06-06
JS+CSS實(shí)現(xiàn)可拖拽的漂亮圓角特效彈出層完整實(shí)例
這篇文章主要介紹了JS+CSS實(shí)現(xiàn)可拖拽的漂亮圓角特效彈出層,以完整實(shí)例形式分析了彈出層特效及圓角矩形的實(shí)現(xiàn)技巧,需要的朋友可以參考下2015-02-02
學(xué)習(xí)RxJS之JavaScript框架Cycle.js
這篇文章主要介紹了學(xué)習(xí)RxJS之JavaScript框架Cycle.js ,它是一個(gè)極簡(jiǎn)的JavaScript框架(核心部分加上注釋125行),提供了一種函數(shù)式,響應(yīng)式的人機(jī)交互接口,需要的朋友可以參考下2019-06-06
如何用原生JavaScript實(shí)現(xiàn)輸入驗(yàn)證的界面
在開發(fā)Web應(yīng)用時(shí),表單驗(yàn)證是一個(gè)必不可少的功能,能夠幫助我們確保用戶輸入的數(shù)據(jù)是有效的,這篇文章主要介紹了如何用原生JavaScript實(shí)現(xiàn)輸入驗(yàn)證界面的相關(guān)資料,需要的朋友可以參考下2025-11-11
原生JS控制多個(gè)滾動(dòng)條同步跟隨滾動(dòng)效果
本文要探討的是,當(dāng)這兩個(gè)容器元素的內(nèi)容都超出了容器高度,即都出現(xiàn)了滾動(dòng)框的時(shí)候,如何在其中一個(gè)容器元素滾動(dòng)時(shí),讓另外一個(gè)元素也隨之滾動(dòng)2017-12-12
小程序?qū)崿F(xiàn)抽獎(jiǎng)動(dòng)畫
這篇文章主要為大家詳細(xì)介紹了小程序?qū)崿F(xiàn)抽獎(jiǎng)動(dòng)畫,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2018-12-12

