javascript技巧

关注公众号 jb51net

关闭
首页 > 网络编程 > JavaScript > javascript技巧 > JS import和require区别与对比

JavaScript笔记之import和require的区别与对比

作者:爱睡觉的猫在睡觉

在JavaScript中,require和import都用于模块导入,这篇文章主要介绍了JavaScript笔记之import和require区别与对比的相关资料,文中通过代码介绍的非常详细,需要的朋友可以参考下

前言

在 JavaScript 中,importrequire 都用于引入模块,但它们来自不同的模块规范,在语法、加载时机、作用域、生态支持等方面差异很大。

1.模块系统不同

require- CommonJS 规范

// Node.js 最早的模块系统(服务器端)
const fs = require('fs');
const _ = require('lodash');

import- ES6 模块规范

// 浏览器/现代 Node.js 环境
import fs from 'fs';                    // 默认导入
import { readFile } from 'fs';          // 命名导入
import * as fsModule from 'fs';         // 全部导入
规范代表出现背景
CommonJSrequireNode.js 最早的模块系统(服务器端)
ES Module(ESM)importECMAScript 官方标准(浏览器 & Node)

👉 核心结论

require运行时模块加载机制
import编译期模块声明机制

2.加载时机与特性对比

require:运行时加载

const moduleA = require('./a') // 执行到这里才加载

特点:

import:编译时加载(静态分析)

import moduleA from './a'

特点:

📌 这是 Vite / Rollup / Webpack 能做 Tree Shaking 的根本原因

特性require (CommonJS)import (ES6)
加载时机运行时同步加载编译时静态分析
位置要求可在代码任意位置必须位于模块顶部(除动态导入)
静态分析不支持 Tree Shaking支持 Tree Shaking
异步支持同步加载静态导入同步,动态导入异步
懒加载需配合特定语法原生支持 import() 懒加载

import 只能写在顶层
⛔ 说的是:import x from 'y'

import() 可以写在任何地方
✅ 它是一个返回 Promise 的函数调用

3.懒加载实现方式对比

require的懒加载(Webpack 特定)

// 方式1:require.ensure (Webpack 特定)
const Home = resolve => {
  require.ensure(['./views/Home.vue'], () => {
    resolve(require('./views/Home.vue'));
  });
};

// 方式2:动态 require (Webpack)
const About = () => {
  return new Promise(resolve => {
    require(['./views/About.vue'], resolve);
  });
};

import的懒加载(ES6 标准)

// 标准 ES6 动态导入
const Home = () => import('./views/Home.vue');

// 更复杂的懒加载配置
const UserProfile = () => ({
  component: import('./UserProfile.vue'),
  loading: LoadingComponent,
  delay: 200,
  timeout: 3000
});

4.实际打包效果

require的打包

示例 :require

// main.js
const utils = require('./utils')
utils.a()

打包结果(简化)

function a() {}
function b() {}
const utils = { a, b }
utils.a()

📌 结论

👉 require 整包引入,无法安全删除 b

import的打包

示例 :静态 import

// utils.js
export function a() {}
export function b() {}
// main.js
import { a } from './utils'
a()

打包结果(简化)

function a() {}
// b 被删除(Tree Shaking)
a()

📌 结论

👉 import 能在打包阶段精准删除未使用代码。

5、代码拆包(code splitting)差异

import(动态)

import('./About.vue')

打包结果(Webpack / Vite):

// 主 bundle
function loadAbout() {
  return __loadChunk__('about').then(...)
}
// about.chunk.js(独立)
export default About

📌 天然支持拆包

require(动态)

require('./About.vue')

⚠️ 结果:

👉 无法可靠拆包

6、运行时代码结构差异(很重要)

require 打包后(CommonJS Runtime)

(function(modules) {
  function __webpack_require__(id) {
    // 同步加载
  }
})(modules)

特点:

import 打包后(ESM Runtime)

Webpack(转换后)

__webpack_require__.d(exports, {
  a: () => a
})

Vite(生产)

import { a } from './chunk.js'

特点:

Vite 项目里的一个“隐形差异”(很重要)

Vite 的策略

结果:

import { debounce } from 'lodash-es'

👉 只打进 debounce

const _ = require('lodash')

👉 整个 lodash 被打包

包体积 & 性能对比(真实工程影响)

维度importrequire
主包体积更小更大
Tree Shaking
懒加载✅(import())
执行效率更优较差
构建器优化极佳受限

📌 在大型 Vue 项目里,差距可能是 几十 KB ~ 数百 KB

7.现代项目中的使用场景

Node.js 项目

// ES6 模块(Node.js 13+,package.json 中 type: "module")
import express from 'express';
import { createServer } from 'http';

// 或者 CommonJS(传统)
const express = require('express');
const http = require('http');

Vue/React 项目

// 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 模块中导入 CommonJS 模块
import _ from 'lodash';  // lodash 是 CommonJS 模块

// 在 CommonJS 模块中导入 ES6 模块(Node.js)
const fs = require('fs');
const es6Module = await import('./es6-module.mjs');  // 需要异步

// Webpack 环境中可以混合
const oldModule = require('./old-module.js');        // CommonJS
const newModule = import('./new-module.js');         // ES6

8.性能对比

// 测试示例:加载 10 个模块
const modules = ['module1', 'module2', 'module3'];

// require - 同步,阻塞执行
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支持静态分析

// 只导入需要的部分,打包时未使用的代码会被移除
import { Button, Input } from 'antd';    // Tree Shaking 生效
import 'antd/dist/antd.css';

// 动态导入也支持 Tree Shaking
const { Modal } = await import('antd');

为什么import能 Tree Shaking?

import { a } from './utils'

构建器在 编译阶段 就知道:

require不支持 Tree Shaking

// 整个模块都会被加载
const antd = require('antd');  // 整个 antd 包都会被包含
const Button = antd.Button;

为什么require不行?

const mod = require('./' + name)

构建器 无法确定

👉 只能保守处理:全留

10.总结选择建议

场景推荐使用原因
现代前端项目importES6 标准,支持 Tree Shaking,更好的懒加载
Node.js 新项目import (ES6 模块)官方推荐,更好的异步支持
Node.js 旧项目require保持兼容性
路由懒加载import()语法简洁,标准支持
条件加载import()异步,可配合条件判断
需要同步加载require 或静态 import立即需要模块时

11.最佳实践示例

// 1. 主应用使用静态导入
import Vue from 'vue';
import Router from 'vue-router';

// 2. 路由使用动态导入懒加载
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. 预加载(提高用户体验)
const preloadModules = [
  import('./views/Products.vue'),   // 预加载可能访问的页面
  import('./views/Contact.vue')
];

核心结论

总结 

到此这篇关于JavaScript笔记之import和require区别与对比的文章就介绍到这了,更多相关JS import和require区别与对比内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

您可能感兴趣的文章:
阅读全文