简体   繁体   中英

AngularJS + TypeScript + ES6 modules: how to bundle for browser?

I'm using Angular, TypeScript, and the ES6 module syntax. Let's suppose I have a module defined as follows:

// SubModule.ts
import MyService from 'services/MyService';

export default angular.module('subModule', [])
    .service('myService', MyService);

The compiled JavaScript would be:

var MyService_1 = require('services/MyService');
exports.default = angular.module('subModule', [])
    .service('myService', MyService_1.default);

My app depends on that module. So I have the following in the App.ts file:

// App.ts
import SubModule from 'modules/SubModule';

angular.module('app', [SubModule.name]);

With the following compiled JavaScript:

var SubModule_1 = require('modules/SubModule');
angular.module('app', [SubModule_1.default.name]);

So, now I'm trying to bundle this for the browser. I'm currently trying to use Browserify, but I'm willing to use any bundling tool available. Browserify gives me an error such as:

Cannot find module 'modules/SubModule' from 'C:\\the\\path\\to\\my\\app'

So how do I make Browserify work? Or is there another tool that would work better? I found this issue on Github that seems to say that default exports from TypeScript aren't interoperable with CommonJS . So what do I do?


EDIT So I think I've found the problem. Browserify requires that local paths start with ./ . So, for example, I would need to reference my sub-module as follows:

import SubModule from './modules/SubModule';

Does anybody know of a Browserify plugin that will automatically look for a relative path even if I don't specify ./ ? My app is rather large, and I don't want to have to go through and modify all import statements.

Or, on the other hand, is there a TypeScript compiler option to emit './modules/SubModule' for 'modules/SubModule' ?

You can use JSPM/Systemjs to load modules asynchronously like:

System.import('./packageName/ModuleName')

and systemjs-builder to create bundles with commandline tool (jspm-cli)

jspm bundle ./packageName/ModuleName dist/app.js

or with gulp task using:

var Builder = require('jspm').Builder;
var builder = new Builder();
builder.loadConfig('jspm.conf.js')
    .then(function() {
        var buildConfig = {
            sfxFormat: 'amd',
            minify: true,
            sourceMaps: true
        };
        return builder.buildSFX('./packageName/ModuleName', outFile, buildConfig);
    });

Here you can see full working example: https://github.com/b091/ts-skeleton

If you do not specify it, browserify will look into NPM packages (from node_modules forlder). The ./ is needed if you want to say "It is one of my files, not a module."

NOTE:

For the problem of a big project, I would do a simple BASH script like this :

files=`find . -type f`
from="from 'modules/"
to="from './modules/"

for file in $files
do 
    sed -i 's/$from/$to/g' $file
done

IMO, the whole point of Browserify was to "ify" the NodeJS / CommonJS modular structure on the server, over to the browser / client-side. If you think of it like that, then you wouldn't want to change the behavior of the import/require statement, keep the "./", so you maintain the symmetry as it should be inline with the common require syntax in NodeJS. I think it's just good coding practice.

I created a gulp adaptor for exactly this purpose. It builds module bundles from Typescript ES6 module syntax using extensions in the tsconfig.json typescript project file. The gulp build then puts all the components together into a single combined javascript bundle. I've recently ported the Typescript-Angular todoMVC app to use typescript ES6 syntax which is compiled and build with TsProject. It is fully documented on the TsProject TodoMVC github site. Please see if it meets your needs.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM