我应该排除模块化Typescript项目的依赖项吗?

时间:2016-11-03 15:02:13

标签: typescript npm browserify

我目前正在尝试为Typescript项目创建一个NPM包(我正在使用gulp和browserify构建)。问题是包消费者当前没有使用模块,因此我尝试使用Browserify打包独立包。

首先,捆绑所有依赖项可能是一个问题吗?据我所知,捆绑的js文件只是将我的依赖项(三个和hammerjs)包装到全局命名空间中。我的包消费者有另一个组件,包括hammerjs(几乎相同的版本),所以我怀疑最后包含的组件将定义我的应用程序可用的hammerjs包?其他以独立方式工作的NPM包如何处理这个?

我发现Browserify可以通过将bundleExternal设置为false或逐个排除依赖关系然后在浏览器中包含这些库来简单地排除其依赖关系。这不起作用,我得到一个"找不到模块' hammerjs'"控制台中出错。我找到了how to use the exclude in browserify?以及如何分别浏览所有依赖项,这些依赖项也有效,但是我可以告诉它,就像简单地将它们捆绑在一起一样,因为我不能简单地从它们中包含hammer.min.js文件网站?

TL; DR

捆绑模块化Typescript NPM包并处理依赖关系以在不支持模块的应用程序中使用的正确方法是什么?

2 个答案:

答案 0 :(得分:2)

要构建一个正在运行的npm软件包,您需要在以package.json为主要方式的spiecified中传递模块。 通常,这应该在dist/my-main-class.js内。

所以在我的src里面我有一个代表我的项目的类/模块/命名空间:

class MyMainClass{
 static myMethod = function(){
    console.log('hello');
 }
}

在文件的最后我有这个:export = MyMainClass;

如果我使用名称MyMainClass $ npm publish MyMainClass发布我的包,我的用户只能使用以下内容导入:

let MyMainClass = require('MyMainClass');
MyMainClass.myMethod();

不要忘记在发布之前构建。 这就是我确定永远不会忘记的方式:

"build": "tsc -p .",
"prepublish": "npm run build",

如果您想缩小代码或执行其他操作,可以在发布之前使用gulp / webpack并定位您的dist文件夹。

"minify": "gulp/grunt/webpack minify dist/**.js",
"build": "tsc -p .",
"prepublish": "npm run build && npm run minify",

答案 1 :(得分:0)

我仍然不太确定处理依赖关系的最佳方法,但我选择使用的路线是创建一个mylib.js和一个mylib.min.js,它们分布在npm包中,不包含任何内容依赖。除了分布式的js文件,我还以模块化的形式包含了库,可以使用例如browserify。我使用browserify的问题是我试图排除库的输出仍然依赖于某种形式的需求,当我尝试使用webpack时,它开箱即用。

我包含了完整的构建脚本以供参考。

文件结构

├───dist                // Output folder for all my distributable standalone js files
│   ├───mylib.d.ts      // Manually writtes declaration file
│   ├───myLib.js        // Distributable without dependencies
│   └───myLib.min.js    // Compressed distributable without dependencies
├───lib
│   ├───myLib.js        // Compiled src
│   └───myLib.d.ts      // Compiled d.ts 
├───src                 // Folder containing my Typescript src
├───tests               // Output folder for my tests
└───testSrc             // Src folder for my test code
    ├───test.html
    └───unittests

的package.json

{
  "name": "mylib",
  "version": "0.0.0",
  "private": true,
  "scripts": {
    "build": "gulp compile && gulp webpack",
    "prepublish": "gulp prepublish"
  },
  "main": "lib/mylib.js",
  "typings": "lib/mylib",
  "dependencies": {
    "@types/es6-promise": "0.0.32",
    "@types/hammerjs": "2.0.33",
    "@types/three": "0.0.24",
    "es6-promise": "4.0.5",
    "hammerjs": "2.0.8",
    "three": "0.82.1"
  },
  "devDependencies": {
    "@types/jasmine": "2.5.37",
    "gulp": "3.9.1",
    "gulp-cli": "1.2.2",
    "gulp-concat": "2.6.0",
    "gulp-copy": "0.0.2",
    "gulp-jasmine": "2.4.2",
    "gulp-preprocess": "2.0.0",
    "gulp-typescript": "3.1.2",
    "jasmine": "2.5.2",
    "ts-loader": "1.0.0",
    "typescript": "2.0.6",
    "webpack-stream": "3.2.0"
  }
}

Gulpfile.js

var gulp = require('gulp');
var ts = require('gulp-typescript');

// Create projects from tsconfig.json
var tsProject = ts.createProject('tsconfig.json');
var mainTestTsProject = ts.createProject('testSrc/tsconfig.json');
var jasmineTsProject = ts.createProject('testSrc/unittests/tsconfig.json');

// External build libraries
var jasmine = require("gulp-jasmine");
var concat = require("gulp-concat");
var copy = require("gulp-copy");
var preprocess = require("gulp-preprocess");
var webpack = require("webpack-stream");

// Compile the modular library
gulp.task('compile', function () {
    return tsProject.src()
        .pipe(tsProject())
        .pipe(gulp.dest("lib"));
});

// Pack and distribute
gulp.task('webpack', function (callback) {
    var config = require("./webpack.config.js");
    return tsProject.src()
        .pipe(webpack(config))
        .pipe(gulp.dest('./dist'))
});

// Pre-process the test.html
gulp.task('preprocessMainHtml', function () {
    return gulp.src('./testSrc/*.html')
        .pipe(preprocess({ context: { CURRENT_TIMESTAMP: Date.now() } }))
        .pipe(gulp.dest('./tests/'));
});

// Copy output libraries for testing
gulp.task('copyLibs', function () {
    return gulp.src(['./dist/*.js', './dist/*.map'])
        .pipe(copy('./tests', { prefix: 1 }));
});

// Compile the test-html main javascript file
gulp.task('compileMainTest', ['copyLibs', 'preprocessMainHtml'], function (callback) {
    return mainTestTsProject.src()
        .pipe(mainTestTsProject())
        .pipe(concat('mylib-test.js'))
        .pipe(gulp.dest("tests"));
});

gulp.task('prepublish', ['compile', 'webpack']);

gulp.task('test', ['compile'], function () {
    return jasmineTsProject.src()
        .pipe(jasmineTsProject())
        .pipe(gulp.dest("tests/unittests"))
        .pipe(jasmine());
});

gulp.task("default", ['webpack', 'compileMainTest']);

webpack.config.js

module.exports = {
    resolve: {
        extensions: ['', '.js', '.ts', '.tsx']
    },
    module: {
        loaders: [
            { test: /\.tsx?$/, loader: 'ts' },
        ]
    },
    externals: {
        "hammerjs": "Hammer",
        "three": "THREE"
    },
    entry: {
        "MyLib": ['./src/mylib.ts'],
    },
    output: {
        path: __dirname + '/dist',
        filename: 'mylib.js',
        libraryTarget: "umd",
        library: 'MyLib'
    },
    devtool: 'source-map',
    debug: true
}

手写的声明文件

// Manually maintained declaration file

// External references
/// <reference types="hammerjs" />
/// <reference types="three" />

// This namespace should map to what is exported in the Gruntfile.js
export as namespace MyLib;

export declare class MyMainClass {
    constructor(a: string);
}

test.html中的Js src

<!-- All mylib.js dependencies -->
<script src="../node_modules/three/build/three.js?_=<!-- @echo CURRENT_TIMESTAMP -->"></script>
<script src="../node_modules/hammerjs/hammer.js?_=<!-- @echo CURRENT_TIMESTAMP -->"></script>

<!-- mylib.js library -->
<script src="./mylib.js?_=<!-- @echo CURRENT_TIMESTAMP -->"></script>

<!-- mylib.js test source -->
<script src="./mylib-test.js?_=<!-- @echo CURRENT_TIMESTAMP -->"></script>