Search code examples
angulartypescriptgulpbrowserifytsify

Separate vendor and app bundles with angular2 and browserify - Import error


I'm working on an angular2 app that I want to build using gulp and browserify.
Using tsify I managed to output a standalone bundle.js, at a glorious size of 1.4M after minification.

What I would like to have is two separate bundle files: one for vendor dependencies and one for my app.

Basically I was hoping to achieve this:

  <!-- My dream index.html script tags -->
  <script src="bundle_vendors.js"></script>
  <script src="bundle_app.js"></script>

Here's what I tried on the command line:

  1. I generated a first bundle:

    browserify app/vendor.ts -p [tsify ] > bundle_vendors.js
    

My vendor.ts file is just a list of imports:

import 'zone.js'
import 'reflect-metadata'
import '@angular/core'
import '@angular/http'
import '@angular/router'
import '@angular/common'
import '@angular/platform-browser'
import '@angular/platform-browser-dynamic'
import 'rxjs/Rx'
  1. Then I created my second bundle:

    browserify -x @angular/core -x @angular/common -x @angular/http -x @angular/router -x rxjs/Rx -x @angular/platform-browser -x zone.js -x reflect-metadata -x @angular/platform-browser-dynamic app/main.ts -p [tsify ] > bundle_app.js
    

My tsconfig.json file looks like this (it lives in the current directory):

{
  "compilerOptions": {
    "target": "ES5",
    "module": "commonjs",
    "moduleResolution": "node",
    "lib": ["es6", "dom"],  
    "sourceMap": true,
    "emitDecoratorMetadata": true,
    "experimentalDecorators": true,
    "removeComments": true,
    "noImplicitAny": false
  },
  "compileOnSave": false,
  "exclude": [
  ]
}

The good part: The second bundle contains only my app and it is much smaller!
The not-so-good part: It does not work. I'm the browser I get an Uncaught Error: Cannot find module '@angular/core'.

Onto the questions:

  • Is there something obvious I'm missing?
  • How can I see the modules that are available for require after I loaded the bundle_vendors.js? I'm looking for the list of modules that are 'exported' so other bundles can import them.

I have no clue where to start debugging this.

From what I read an alternative would be to use angular-cli (which uses webpack), but the project I work on already uses gulp so I'd like to make it work. Plus I'm kinda committed now.

Any help appreciated!


Solution

  • There are two problems:

    1. You have not used the -r option for the modules you wish to require from bundle_vendors.js.
    2. There is a bug in tsify that breaks Browserify's -r option.

    I've fixed the second problem and a new version of tsify (3.0.0) has been publised to NPM.

    To fix the first, you should change the command used to build bundle_vendors.js to:

    browserify -r @angular/core -r @angular/common -r @angular/http -r @angular/router -r rxjs/Rx -r @angular/platform-browser -r zone.js -r reflect-metadata -r @angular/platform-browser-dynamic app/vendor.ts -p [tsify] > bundle_vendors.js
    

    Also, you might want to consider adding the skipLibCheck compiler option to your tsconfig.json:

    TypeScript 2.0 adds a new --skipLibCheck compiler option that causes type checking of declaration files (files with extension .d.ts) to be skipped. When a program includes large declaration files, the compiler spends a lot of time type checking declarations that are already known to not contain errors, and compile times may be significantly shortened by skipping declaration file type checks.