您现在的位置是:首页 > 正文

SystemJS

2024-01-30 19:43:46阅读 0

最近的工作有用到SystemJS,在这里对SystemJS的理解做个总结和记录吧,备忘。


什么是SystemJS

SystemJS是一个可运行于浏览器端的模块加载器,是一个polifill,可以让我们在浏览器上直接使用ES模块等先进语法,而不用管浏览器是否支持该语法。

对应的,SystemJS有一个运行于Nodejs的版本:system-node.cjs。

为什么会出现SystemJS

Chrome浏览器其实已经支持js代码中的import、export有一段时间了,语法规则为

<script type="module" src="xxx"></script>

这个特性可以让我们在浏览器端import一个js模块,例如:

//在html里
<script type="module" src="./index.js"></script>


//然后在 index.js 中可以直接使用import
import lodash from "https://cdn.bootcdn.net/ajax/libs/lodash.js/4.17.20/lodash.min.js";

我们也可以通过名称来 import 一个 js 模块:

import lodash from "lodash";

注意:本地不需要安装lodash模块,但需要我们写一个importmap配置:

<script type="importmap">
  {
    "imports": {
      "lodash": "https://cdn.bootcdn.net/ajax/libs/lodash.js/4.17.20/lodash.min.js" 
    }
  }
</script>

Chrome是目前唯一实现importmap的浏览器,以上写法,要开启chrome的feature标记才可以体验。在普通模式下,上述写法是会报错的。如果想要在普通模式下使用importmap,那就要用到SystemJS了。

SystemJS是一个支持importmaps和其他js未来特性的pollyfill,这意味着你可以在IE11或者任何浏览器下使用importmaps而不用等这些浏览器支持importmaps等特性。

SystemJS的几个特性

除了importmaps,SystemJS还有5个让你现在就可以使用 js 模块新特性的能力,这些特性是不能直接依赖浏览器来使用的。其中importmaps是当中最重要的一个。

1.  importmaps。 

2. 通过1个文件加载多个js模块。正常情况下,加载一个js文件必须发起1次网络请求,如果只使用浏览器的能力,100个js文件就要发100个网络请求。通过SystemJS,允许你通过system.set 和 system.register apis,一次网络请求加载多个js文件。 

3. 检测已注册模块,通过 system.get 和 system.has,system.entries apis 可以查看所有可用的js模块。 

4. import.meta.resolve,得到任何模块的完整url。如果浏览器不支持import.meta,可以改为使用 systemjs.contex.meta.resolve。 

5.  Import.meta.url, 返回当前模块的url。 

6. 除了js模块,SystemJS还支持其他类型模块,如下类型已经进入提案:json模块、css模块、html模块等,这些模块的加载,浏览器暂时还不支持,但是SystemJS已经支持。 

如何使用SystemJS

首先,要修改script标签的type,由`importmap`改为`systemjs-importmap`。

- <script type="importmap">


+ <script type="systemjs-importmap">
  {
    "imports": {
      "lodash": "https://cdn.bootcdn.net/ajax/libs/lodash.js/4.17.20/lodash.min.js" 
    }
  }
</script>

接着,引入模块的script也要修改type,由`module`改为`systemjs-module`。

- <script type="module" src="./index.js"></script>


+ <script type="systemjs-module" src="./index.js"></script>

除了使用`systemjs-module`我们还可以直接在script标签里`Syetem.import('./xxx.js'); `(这种写法更常见)。

然后,我们不能在模块中再使用import关键字了。

SystemJS维护它自己的js模块列表,与浏览器跟踪的js模块不一样,如果继续在浏览器使用import,浏览器识别它,并会去跟踪查明它到底是什么模块,而我们正在使用的是一个浏览器在未来才会支持的特性,所以浏览器会报错。所以我们要使用另一种只有SystemJS才能理解而不被浏览器去解析的语法System.register:

- import lodash from 'lodash';


+ System.register(['lodash'], (exports) => {
+    return {
+      setters: [
+        () => {};
+      ],
+      execute() {
+        console.log('test');
+        exports({_: lodash});
+      })
+    }
+  }
+ })

这个语法,打包工具(例如webpack或者rollup)会自动帮我们转换,省得咱们去记。

在webpack下只需要将libraryTarget设置为system即可:

// Webpack 关键配置
{
  output: {
    libraryTarget: 'system', 
  }
}

rollup中配置的是format字段:

// rollup 关键配置
output: {
    format: 'system',
},

最后,我们要在页面加载SystemJS。

使用script标签加载:

<script src="https://lib.baomitu.com/systemjs/latest/system.js"></script>

总结起来,就是我们需要:加载SystemJS、配置systemjs-importmap和systemjs-module(或者使用system.import)、加载使用 `sytemjs.registry` 代替 `import` 的 js 模块,然后刷新页面就就可以看到运行效果了。

需要注意的是:

配置 systemjs-import 的资源url时候,url对应的资源内容不能是 es6 module(有import和export)必须是es5 module。

Unable to resolve bare specifier 报错的解决

使用SystemJS的过程中,如果遇到`Unable to resolve bare specifier xxx`的报错,那是因为SystemJS找不到`xxx`对应的url。而通过importmaps ,SystemJS可以将 “bare specifier” 转换为URL,所以此时只需要配置importmap将对应的资源地址告诉SystemJS即可。

另外,以下几种行为,会触发 SystemJS 获取模块的 url:

• 直接加载模块:System.import('specifier')

• 将模块作为依赖来加载:System.register(['specifier'], ...) 

• 手动resolve:System.resolve('specifier')

更多SystemJS错误处理可参考:

https://github.com/systemjs/systemjs/blob/master/docs/errors.md#8

- End -

前端手札

一名WEB技术爱好者的手札

08743446776e3ee3f8b9019d717074bf.png

网站文章

  • C/S客户端调用RESTful API帮助类

    文章目录 目录 文章目录 简介 一、源码 1.HttpClientHelper帮助类 2.ContentType枚举类 3.表单Form元素类 4.HttpClient、MultipartFormDa...

    2024-01-30 19:43:39
  • API拦截—实现Ring3全局HOOK

    魏滔序注:本转载内容仅用来技术研究,请勿于损人害己之用。 首先来解释一下这次的目标。由于windows的copy-on-write机制(Ring0下可以用CR0寄存器关掉它),Ring3下的HOOK只对当前进程有效,其他进程的API还是正常的。这就是说我们必须枚举进程,然后对每个Ring3进程执行一遍HOOK操作。但是,系统中总有新进程产生,对于这些新进程我们怎么处理

    2024-01-30 19:43:09
  • 北京工作三年程序员,2018年4~5月面试经历

    1、新东方 04_19 技术面试,两轮,地点:中关村地铁站E口,鼎好大厦6层, 面试官:龙彦俊,李经理 面试时间:2018_04_19_10:30(提前到了45分钟) 1、自我介绍 2、项目介绍 3、LiveChat项目,第一个 4、海南海航项目,第二个,最熟悉 5、技术: 数据库 mysql mysql如何做主从/主主复制的,java程序如何操作的? mysql主从...

    2024-01-30 19:43:01
  • spring boot 项目练习

    spring boot 项目练习

    spring boot官方文档:https://docs.spring.io/spring-boot/docs/current/reference/html/ 浏览器发送hello请求,服务器接受请求并处理,响应Hello World字符串; 1.创建一个maven工程 2.导入依赖 org.springframework.boot sprin

    2024-01-30 19:42:54
  • “注释: 爱恨交织的双重标准?解析注释在代码开发中的作用。”

    “注释: 爱恨交织的双重标准?解析注释在代码开发中的作用。”

    代码注释是程序员在开发过程中经常会遇到的问题之一。有些程序员认为注释非常必要,因为它们可以解释代码中的意图和功能。但是也有一些程序员不喜欢写注释,因为他们认为代码应该是自描述的,不应该需要注释来阐明自己的意图。不管是哪种立场,都有它的道理。在这篇文章中,我将探讨程序员对注释的看法,并分享我对于不写注释的程序员的看法。

    2024-01-30 19:42:25
  • 块级作用域和函数作用域

    块级作用域和函数作用域

    函数作用域与块级作用域 函数作用域:在函数内部声明的变量只能影响到变量所在函数体本身,无法从外部对函数内部的变量进行调用,被称为‘函数作用域’ 块级作用域:ES6 引入了 let 和 const 关键...

    2024-01-30 19:42:18
  • [AcWing] 148. 合并果子(C++实现)贪心---哈夫曼树例题

    [AcWing] 148. 合并果子(C++实现)贪心---哈夫曼树例题

    [AcWing] 148. 合并果子(C++实现)贪心---哈夫曼树例题1. 题目2. 读题(需要重点注意的东西)3. 解法4. 可能有帮助的前置习题5. 所用到的数据结构与算法思想6. 总结 1. ...

    2024-01-30 19:42:11
  • 计算机级C语言实例:使用C#编写的简单计算器

    然后,使用Console.ReadLine()函数接收用户输入的两个数字和运算符,并将它们转换为相应的数据类型。如有任何疑问,请随时提问。在本篇文章中,我们将使用C#编写一个简单的计算器应用程序。最后...

    2024-01-30 19:42:06
  • IL伪指令

    IL伪指令 在IL程序中,以“.”开头的指令代表是将要传输给汇编工具的指令,即伪指令。该指令要汇编工具执行某些具体操作。.assembly <程序集名称> {}//指明IL码属于那个程序集。.method 修饰符 返回值 名称(参数列表){...

    2024-01-30 19:41:26
  • 微型计算机usb接口通常串行,第一章-微型计算机组成题库.doc

    《第一章微型计算机组成概述》练习判断题1. 光盘是一种可读不可写的存储器。2. 显示器直接与PCI-E接口相连。3. 激光打印机使用的墨水质量很高。4.SRAM比DRAM速度慢。5.ROM是非易失性存...

    2024-01-30 19:41:19