通用打字稿 npm 模块

Universal typescript npm module

我正在修改一个现有的库,以便它可以在打字稿中导入。我把它归结为 Minimal working example

要求

到目前为止我得到了什么

图书馆

文件结构:

│   package.json
│   rollup.config.js
│   tsconfig.json
│   yarn-error.log
│   yarn.lock
│
└───src
        lib.ts
        options.ts

package.json:

{
  "name": "library",
  "version": "1.0.8",
  "description": "example library",
  "main": "dist/lib.umd.js",
  "module":"dist/lib.esm.js",
  "types":"dist/types/lib.d.ts",
  "license": "MIT",
  "private": true,
  "devDependencies": {
    "@rollup/plugin-typescript": "^8.3.0",
    "rollup": "^2.67.0",
    "tslib": "^2.3.1",
    "typescript": "^4.5.5"
  },
  "exports": {
    "import": "./dist/lib.esm.js",
    "require": "./dist/lib.umd.js"
  },
  "scripts": {
    "build:types": "tsc -d --emitDeclarationOnly",
    "build:js": "rollup -c rollup.config.js",
    "build:minjs:umd": "terser dist/index.umd.js --compress --mangle > dist/index.umd.min.js",
    "build:minjs:esm": "terser dist/index.esm.js --compress --mangle > dist/index.esm.min.js",
    "build:minjs": "npm run build:minjs:esm -s && npm run build:minjs:umd -s",
    "build": "npm run build:js -s && npm run build:minjs -s && npm run build:types -s",
    "prepublishOnly": "npm run lint -s && npm test -s && npm run build",
    "semantic-release": "semantic-release"
  },
  "type":"module"
}

rollup.config.js:

import typescript from '@rollup/plugin-typescript';

export default {
  input: 'src/lib.ts',
  output: [
    {
      file: 'dist/lib.esm.js',
      format: 'es',
    },
    {
      file: 'dist/lib.umd.js',
      format: 'umd',
      name: 'Lib',
    },
  ],
  plugins: [typescript({tsconfig:'./tsconfig.json'})],
};

tsconfig.json:

{
  "compilerOptions": {
    "target": "es2016",
    "module": "esnext",
    "moduleResolution": "node",
    "declaration": true,
    "outDir": "./types",
    "forceConsistentCasingInFileNames": true,
    "strict": true,
    "skipLibCheck": true
  },
}

src/lib.ts:

import Options from "./options";

export default class Lib{
    constructor(options:Options){
        console.log("It works!");
        console.log(options.message);
    }
}

options.ts:

export default interface Options {
    message: string;
}

我正在使用 yarn build:js.

编译所有这些

使用图书馆

<script> 个标签

当我将生成的 lib.umd.js 复制到文件夹并创建 index.html:

<script src=lib.umd.js></script>
<script>
    var a = new Lib({message:"message here"});
</script>

有效。到目前为止一切顺利。

在另一个打字稿项目中

接下来,我创建了一个使用我的库的简单打字稿项目。

文件结构:

│   gulpfile.js
│   package.json
│   tsconfig.json
│   yarn.lock
│
├───dist
│       index.html
│
└───Scripts
        Index.ts

package.json 中,我将我的库作为依赖项,连同 jQuery 以希望排除该项目的不正确配置:

{
    "private": true,
    "version": "1.0.0",
    "scripts": {
        "preinstall": "npx use-yarn",
        "gulp": "node_modules/.bin/gulp"
    },
    "name": "ts-import",
    "devDependencies": {
        "@types/jquery": "^3.5.13",
        "gulp": "^4.0.2",
        "gulp-browserify": "^0.5.1",
        "gulp-clean": "^0.4.0",
        "gulp-concat": "^2.6.1",
        "gulp-sourcemaps": "^3.0.0",
        "gulp-typescript": "^6.0.0-alpha.1",
        "gulp-uglify": "^3.0.2",
        "typescript": "^4.5.5",
        "vinyl-source-stream": "^2.0.0"
    },
    "dependencies": {
        "jquery": "*",
        "library": "file:../../library"
    }
}

tsconfig.json:

{
    "compilerOptions": {
        "noEmitOnError": true,
        "noImplicitAny": true,
        "sourceMap": true,
        "target": "es5",
        "moduleResolution": "node",
        "outDir":"./js"
    },
    "compileOnSave": true,
    "exclude": [
        "**/node_modules/**"
    ],
    "include":[
        "./Scripts"
    ]
}

我正在使用 gulp 编译 ts 和解析导入 - gulpfile.js:

const gulp = require('gulp');
const {series} = require('gulp');
const clean = require('gulp-clean');
const ts = require('gulp-typescript');
const sourcemaps = require('gulp-sourcemaps');
const browserify = require('gulp-browserify');
const concat = require('gulp-concat');
const uglify = require('gulp-uglify');

function cleanAll(cb) {
  return gulp.src([
      "./tmp/",
      "./dist/js"
    ], { read: false, allowEmpty: true })
    .pipe(clean());
}

function transpileTS() {
  const tsproject = ts.createProject('./tsconfig.json');
  return tsproject
      .src()
      .pipe(sourcemaps.init())
      .pipe(tsproject()).js
      .pipe(sourcemaps.write('./sourcemaps'))
      .pipe(gulp.dest('./tmp/js'));
}

function minJS() {
  return gulp
      .src('./tmp/js/Index.js')
      .pipe(sourcemaps.init({ loadMaps: true }))
      .pipe(browserify())
    //   .pipe(uglify())
      .pipe(concat('index.min.js'))
      .pipe(sourcemaps.write('./sourcemaps'))
      .pipe(gulp.dest('./dist/js'))
}

exports.default = series( cleanAll, transpileTS, minJS );

我正在像这样导入和使用我的库 - Scripts/Index.ts:

import * as $ from "jquery";
import Lib from "library";

$(()=>{
    console.log("creating lib instance.");
    new Lib({message:"example message here"});
});

但是当我在浏览器中启动它时 - dist/index.html:

<script src="js/Index.min.js"></script>

我得到一个错误:

Uncaught TypeError: library_1.default is not a constructor

的确,library_1.default不存在,library_1确实存在:

> library_1
< class Lib {
        constructor(options) {
            console.log("It works!");
            console.log(options.message);
        }
    }

我该如何解决这个问题?我怀疑错误是在图书馆的某个地方,但我不知道在哪里。

我已经弄明白了。 在我的 lib.ts 中,我不得不更改导出 class:

的方式
import Options from "./options";

class Lib{
    constructor(options:Options){
        console.log("It works!");
        console.log(options.message);
    }
}

export default Lib;

接下来,我更改了 rollup.config.js(添加了 exports:'default')以保持导出的 class 全局:

...
{
      file: 'dist/lib.umd.js',
      format: 'umd',
      name: 'Lib',
      exports:'default'
},
...

我还必须更改库的 package.json - 我将 main 指向我的 es 模块,因为它看起来像 browserify 只是忽略了模块指令。
我还最终删除了 exports 部分,因为我们的一些其他项目(不使用 browserify)继续使用 require 文件,而不是 import 文件:

{
  "name": "library",
  "version": "1.0.16",
  "description": "example library",
  "main": "dist/lib.esm.js",
  "module":"dist/lib.esm.js",
  "types":"dist/types/lib.d.ts",
  "license": "MIT",
  "private": true,
  "devDependencies": {
    "@rollup/plugin-typescript": "^8.3.0",
    "rollup": "^2.67.0",
    "tslib": "^2.3.1",
    "typescript": "^4.5.5"
  },
  "exports": {
    "import": "./dist/lib.esm.js",
    "require": "./dist/lib.umd.js"
  },
  "scripts": {
    "build": "rollup -c rollup.config.js"
  }
}

最后,我不得不在我的消费者项目中使用 babelify 来避免 ParseError: 'import' and 'export' may appear only with 'sourceType: module' 而 运行 browserify。

完整的源代码可用here