如何在JavaScript文件中引入另一份JavaScript文件?

问题描述

在JavaScript中,是否有类似CSS @import的语句,使之能够在JavaScript文件中引入其他JavaScript文件?

解决方案

在老版本的JavaScript文件中,不存在importincluderequire,所以针对这一问题出现了许多解决方案。

自从ES6诞生以来,JavaScript就有了标准的模块方案,大多数现代浏览器都支持这个方案。

如果为了兼容老版本的浏览器,可以使用构建工具或者编译工具

Node.js中的ES6模块

Node.js从8.5版本已经开始支持ES6模块了,但需要启用--experimental-modules标志,所有的文件也必须以.mjs结尾。

// module.mjs
export function hello() {
  return "Hello";
}
// main.mjs
import { hello } from 'module'; // 或者 './module'
let val = hello();  // val 为 "Hello";

浏览器中的ES6模块

Safari 10.1、Chrome 61、Firefox 60和Edge 16等版本的浏览器中都可以直接使用ES6模块语法了,不需要借助webpack之类的工具,你可以在caniuse中查找相关的兼容性。

<script type="module">
  import { hello } from './hello.mjs';
  hello('world');
</script>
// hello.mjs
export function hello(text) {
  const div = document.createElement('div');
  div.textContent = `Hello ${text}`;
  document.body.appendChild(div);
}
在浏览器中进行动态导入

动态引入可以让脚本在需要的时候再进行加载:

<script type="module">
  import('hello.mjs').then(module => {
      module.hello('world');
    });
</script>

Node.js require

module.exports/require在Node.js中依然是使用的最为广泛的模块导入机制。

// mymodule.js
module.exports = {
   hello: function() {
      return "Hello";
   }
}
// server.js
const myModule = require('./mymodule');
let val = myModule.hello(); // val 为 "Hello" 

另外,在浏览器中还有一些不需要预处理的模块导入机制。

AJAX加载

你可以使用AJAX加载脚本,然是使用eval来执行脚本。但是,这种做法受限于浏览器的同源策略,并且eval存在许多问题。

Fetch加载

你可以使用Fetch动态导入一些脚本,它返回一个promise对象,所以你可以控制脚本的加载顺序,下面的代码Fetch Inject库来加载脚本:

fetchInject([
  'https://cdn.jsdelivr.net/momentjs/2.17.1/moment.min.js'
]).then(() => {
  console.log(`Finish in less than ${moment().endOf('year').fromNow(true)}`)
})

jQuery加载

jQuery提供了getScript方法实现了脚本加载:

$.getScript("my_lovely_script.js", function() {
   alert("Script loaded but not necessarily executed.");
});

动态导入脚本

你可以在HTML页面上,插入<script>标签,以此实现脚本的动态导入。

这种方法不受同源策略的限制,并且浏览器自己会执行代码。

下面是一个例子:

function dynamicallyLoadScript(url) {
    var script = document.createElement("script");  // 创建一个`script`节点
    script.src = url;  // 设置src属性

    document.head.appendChild(script);  // 将节点添加到页面上
}

上面的函数将会添加一个<script>标签到页面上,我们将要导入的脚本地址作为参数传入到函数中。

用户头像
登录后发表评论