TypeScript – Get Started Advanced (Work with SystemJS)

更新

我本来想 skip 掉 bundler (webpack), 感觉单侧不需要搞那么复杂, 所以用了 TypeScript 自带的 bundle (outFile) + SystemJS. 谁知道这技术早就落后 n 年了. 真的是太久没有玩前端了.

想 bundle TypeScript 用 esbuild 是最好的, 又快又简单. 看这篇 TypeScript – Work with JavaScript Library (using esbuild).

 

前言

之前写的 TypeScript – Get Started 太简单了, 想依赖个 library 都做不到. 于是就有了这篇进阶版本.

这已经是尽可能不依赖 bundler (e.g. Webpack) 情况下, 让它跑起来了.

TypeScript 有基本的 bundler 功能, 配上 SystemJS 就可以做到模块化单元测试了.

 

参考

medium – TypeScript: Start a Browser-based Project Using the System.js

Youtube – SystemJS Explaination

 

SystemJS 介绍

在 JavaScript – Modular 有提到过 SystemJS, 前端模块 AMD (RequireJS) > UMD (SystemJS) > ES Module

它属于现阶段最好的过渡方案.

bundle 会把多个 .js 模块变成一个, 这时 ES Module 的 import 就失效了. 所以就要有另一个模块方案. SystemJS 主要就是干这些.

另外, ES Module import 只能写 path (importmap 目前许多 browser 都不支持), 但是我们更希望写名字, 比如 import $ from 'jquery', 

SystemJS 的其中一个功能就是 importmap 的 polyfill.

 

启动项目

mkdir play-typescript
cd play-typescript
yarn init
tsc --init
yarn add typescript --dev

 

HTML

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Document</title>
    <!-- SystemJS -->
    <script
      src="https://cdn.jsdelivr.net/npm/systemjs@6.12.1/dist/s.min.js"
      defer
    ></script>
    <script
      src="https://cdn.jsdelivr.net/npm/systemjs@6.12.1/dist/extras/named-register.min.js"
      defer
    ></script>
    <script
      src="https://cdn.jsdelivr.net/npm/systemjs@6.12.1/dist/extras/amd.min.js"
      defer
    ></script>

    <!-- importmap -->
    <script type="systemjs-importmap">
      {
        "imports": {
          "lodash": "https://cdn.jsdelivr.net/npm/lodash@4.17.21/lodash.min.js",
          "jquery": "https://cdn.jsdelivr.net/npm/jquery@3.6.0/dist/jquery.min.js"
        }
      }
    </script>

    <!-- bundle.js -->
    <script type="systemjs-module" src="./bundle.js"></script>
  </head>
  <body>
    <h1>Hello World</h1>
  </body>
</html>

首先是 3 个 SystemJS 的 files

然后是项目依赖的 Library (jquerylodash) importmap

最后是 TypeScript bundle 出来的 bundle.js

注: 都加了 defer 哦

 

tsconfig

{
  "compilerOptions": {
    "target": "es2016",
    "module": "System", // 关键
    "outFile": "./bundle.js", // 关键
    "esModuleInterop": true,
    "forceConsistentCasingInFileNames": true,
    "strict": true,
    "skipLibCheck": true
  }
}

关键就是 module 和 outFile

 

Typescript

先添加依赖 Library

yarn add jquery
yarn add @types/jquery --dev

yarn add lodash
yarn add @types/lodash --dev

jquery 和 lodash 都没有默认的 .d.ts, 所以需要另外添加 @types

module.ts

import $ from "jquery";
import _ from "lodash";

export function myFunction() {
  $("h1").css("color", "blue");
  _.forEach([1, 2, 3], (index) => $("body").append($(`<h1>${index}</h1>`)));
}

index.ts

import { myFunction } from "./module";

myFunction();

 

运行 tsc and Open with Live Server

运行 command tsc 

然后开启 Live Server

效果

 

TypeScript bundle 出来的 .js 会包含所有的 module, 全部都被 System.register

而最后一个 System.register 会走位 entry point. 这个是 SystemJS 的规则.

视乎没有办法指定 entry point. 这个很麻烦丫. 于是我决定不用 SystemJS, 改用 esbuild bundler.

 

posted @ 2022-05-01 22:27  兴杰  阅读(132)  评论(0编辑  收藏  举报