This is a cross post to https://github.com/systemjs/builder/issues/611
I'm trying to bundle my Angular 2 rc 1 app with systemjs-builder 0.15.16 buildStatic method. An angular component has a view as well as one or more stylesheets external to the script. They are referred to within the #Component metadata in one of two ways
Using absolute paths:
#Component({
templateUrl: 'app/some.component.html',
styleUrls: ['app/some.component.css']
})
Using the now recommended relative paths:
#Component({
moduleId: module.id,
templateUrl: 'some.component.html',
styleUrls: ['some.component.css']
})
My app uses relative paths, and things have been working fine. Today I decided to use systemjs-builder's buildStatic. The resulting file throws 404 errors whenever there is a relative path because the browser is fetching localhost/some.component.html instead of localhost/app/some.component.html. Below is the relevant part of my gulpfile.js
var appDev = 'dev/';
var appProd = 'app/';
var typescript = require('gulp-typescript');
var tsProject = typescript.createProject('tsconfig.json');
var Builder = require('systemjs-builder');
var sourcemaps = require('gulp-sourcemaps');
gulp.task('build-ts', function () {
return gulp.src(appDev + '**/*.ts')
.pipe(sourcemaps.init())
.pipe(typescript(tsProject))
.pipe(sourcemaps.write())
.pipe(gulp.dest(appProd));
});
gulp.task('bundle',['build-ts'], function() {
var builder = new Builder('', './systemjs.config.js');
return builder
.buildStatic(appProd + '/main.js', appProd + '/bundle.js', { minify: false, sourceMaps: true})
.then(function() {
console.log('Build complete');
})
.catch(function(err) {
console.log('Build error');
console.log(err);
});
});
With relative paths, if I run just the build-ts gulp task and browse the "regular" way, things work. If I run the bundle gulp task and try to browse the app using the bundle.js file, the 404 errors occur wherever the app tries to load external templates and stylesheets. I've tried to be explicit about the relative nature of the paths by changing templateUrl: 'some.component.html' to templateUrl: './some.component.html' to no effect. Hard-coding absolute paths everywhere seems like a bad idea. What am I missing?
After a couple of days I got a helpful response from a systemjs member on github.
What did the trick: in the configuration object for systemjs-builder's buildStatic method, set encodeNames to false. So the line...
.buildStatic(
appProd + '/main.js',
appProd + '/bundle.js',
{ minify: false, sourceMaps: true}
)
became...
.buildStatic(
appProd + '/main.js',
appProd + '/bundle.js',
{ minify: false, sourceMaps: true, encodeNames:false}
)
Additional Info
tsconfig.json
{
"compilerOptions": {
"target": "ES5",
"module": "commonjs",
"moduleResolution": "node",
"sourceMap": true,
"emitDecoratorMetadata": true,
"experimentalDecorators": true,
"removeComments": false,
"noImplicitAny": false,
"outDir": "./app"
},
"filesGlob": [
"./dev/**/*.ts",
"!./node_modules/**/*.ts"
],
"exclude": [
"node_modules",
"typings"
]
}
Related
I have created a npm package using typescript react and rollup.js. I have link it to the project using yalc (similar to npm link) and getting the following error:
Server Error
Error: Cannot find module './tslib.es6-eaa548e7.js'
Require stack:
- /Users/paul/Projects/test-project/.next/server/pages/index.js
Package structure:
- dist/
- ContactForm7.d.ts
- ContactForm7.js
- index.d.ts
- tslib.es6-eaa548e7.js
- Wordpress.d.ts
- Wordpress.js
- src/
- package.json
- rollups.config.js
- tsconfig.json
pages/index.tsx is importing the package with:
import { getPage } from 'package-wordpress/dist/Wordpress';
This is the starting contents of dist/Wordpress.js which looks to be initiating the error:
'use strict';
Object.defineProperty(exports, '__esModule', { value: true });
var tslib_es6 = require('./tslib.es6-eaa548e7.js'); // this is where error occurs
var axios = require('axios');
var cacheData = require('memory-cache');
rollup.config.js:
import typescript from '#rollup/plugin-typescript';
import replace from 'rollup-plugin-replace';
import commonjs from '#rollup/plugin-commonjs';
export default {
input: {
Wordpress: 'src/Wordpress.tsx',
ContactForm7: 'src/ContactForm7.tsx'
},
output: {
dir: 'dist',
format: 'cjs',
exports: 'named',
},
plugins: [
typescript({
tsconfig: 'tsconfig.json'
}),
replace({
'process.env.MY_VARIABLE': JSON.stringify(process.env.MY_VARIABLE)
}),
commonjs()
],
external: ['react'],
};
tsconfig.json:
{
"compilerOptions": {
"target": "es5",
"jsx": "react",
"module": "esnext",
"lib": ["esnext"],
"strict": true,
"esModuleInterop": true,
"declaration": true,
"outDir": "dist",
"importHelpers": true
},
"include": [
"src",
"src/index.tsx"
]
}
I want to exclude imported libraries from my result bundle.
Lets say we have next code:
import * as angular from 'angular';
const app = angular.module('app',[]);
And we have this build task.
function buildTs(compileOptions) {
browserify(compileOptions)
.plugin(tsify, tsconfig.compileOptions)
.bundle()
.pipe(source('bundle.js'))
.pipe(gulp.dest(path.dest.js));
}
When build will be finished, Angular lib will be included into bundle.js.
Can I avoid this?
My tsConfig:
{
"compilerOptions": {
"target": "ES5",
"module": "commonjs",
"noImplicitAny": false,
"removeComments": true,
"sourceMap": true,
"types": [
"angular",
"angular-cookies",
"angular-ui-bootstrap",
"angular-ui-router",
"jasmine",
"angular-mocks"
]
},
"include": [
"app"
],
"exclude": [
"node_modules"
]
}
Removing types from types not helps :)
This will make browserify ignore angularjs , and then it can be added from index.html .
var browserify = require("browserify")
browserify()
.ignore('angular')
Any option to include several files without adding .ignore(name) each time? With array or smth like this?
var tsProject = ts.createProject('tsconfig.json');
gulp.task('scripts', function() {
var tsResult = gulp.src("lib/**/*.ts")
// or
tsProject.src()
.pipe(tsProject());
return tsResult.js.pipe(gulp.dest('release'));
});
Thus , this might be a cleaner way to build Typescript files. In src , you can provide your own list of regular expression src files .
Problem: mysterious "Unexpected token export"
I happened to get this error in an Angular example running in plunker where SystemJS transpiles TypeScript code in the browser.
There was nothing wrong with the code which ran fine locally.
Solution
This isn't an Angular problem. It's a problem with transpiling certain kinds of TypeScript files in the browser.
In my case, I tracked the problem down to a single file that only exported an abstract class.
// Class used as a "narrowing" interface that exposes a minimal logger
// Other members of the actual implementation are invisible
export abstract class MinimalLogger {
logs: string[];
logInfo: (msg: string) => void;
}
The problem is that this file doesn't export anything other than the abstract class.
When I add an inert export of anything concrete ... like this:
export const _ = 0; // hack: must export something "real"
... the error goes away.
I've seen a similar problem with a file that only exports TypeScript interfaces. You have to give it at least one thing that is "real".
Environment:
typescript#2.2.1
systemjs#0.19.39
SystemJS Config for this example:
System.config({
// DEMO ONLY! REAL CODE SHOULD NOT TRANSPILE IN THE BROWSER
transpiler: 'ts',
typescriptOptions: {
"target": "es5",
"module": "commonjs",
"moduleResolution": "node",
"sourceMap": true,
"emitDecoratorMetadata": true,
"experimentalDecorators": true,
"lib": ["es2015", "dom"],
"noImplicitAny": true,
"suppressImplicitAnyIndexErrors": true
},
meta: {
'typescript': {
"exports": "ts"
}
},
...
})
Basically I have created a sample application by referring to Angular2 quickstart tutorial. For further digging I've created ./services/dataService.ts service file like below.
import {Injectable} from 'angular2/core';
#Injectable()
export class DataService {
items: Array<number>;
constructor() {
this.items = [1, 2, 3, 4];
}
getItems() {
return this.items;
}
}
I had "outDir": "../wwwroot/app", option mentioned in tsconfig which transpile app.ts & dataService.ts to below path.
--wwwroot
|app
|--app.js
|--services
|-- dataService.js
MyAppComponent
import {Component, View, Inject, forwardRef} from 'angular2/core';
import {NgFor} from 'angular2/common';
import {bootstrap} from 'angular2/platform/browser';
import {DataService} from './services/dataService';
#Component({
'selector': 'my-app',
template: `
<div *ngFor="#item of items">
{{item}}
</div>
`,
directives: [NgFor],
providers: [DataService]
})
export class MyAppComponent {
items: Array<number>;
constructor(service: DataService) {
this.items = service.getItems();
}
}
bootstrap(MyAppComponent)
Code gets compiled with no-error, but after application Ran I got
below error, http://localhost:8413/app/services/dataService.
Failed to load resource: the server responded with a status of 404 (Not Found)
I used below code from index.html to load app files on page.
System.config({ packages: { src: { defaultExtension: 'js' } } });
System.import('app/app.js').then(null, console.error.bind(console));
My question is how could I import the dataService.js, why does is give 404 error still its there in a place? I Researched alot on this problem, but didn't find anything helpful. Any help would appreciated.
Edit
Added .tsconfig to directly get rectify when there is issue
{
"compilerOptions": {
"noImplicitAny": false,
"noEmitOnError": true,
"module": "commonjs",
"removeComments": false,
"sourceMap": true,
"target": "es5",
"outDir": "../wwwroot/app",
"experimentalDecorators": true,
"emitDecoratorMetadata": true
},
"exclude": [
"node_modules",
"wwwroot"
]
}
The problem was with configuration of System, previously I was having below code to load component.
System.config({ packages: { src: { defaultExtension: 'js' } } });
System.import('app/app.js').then(null, console.error.bind(console));
Basically System.config settings tells that packages would be belongs to src folder and the files defaultExtension is js. So I changed my packages's src to app as I was having app folder, not src.
Other than that I changed System.import('app/app.js') to System.import('app/app') as default extensions of files is js, so I don't need to bother about it. So my component loading script changed to below.
System.config({ packages: { app: { defaultExtension: 'js' } } });
System.import('app/app').then(null, console.error.bind(console));
I am working on nodejs application in typescript with angular which is also in typescript. i have use gulp to transpile the files to js. but when i run command to transile my angular file it gives me error TS2300: Duplicate identifier
here is my gulp.config.js
module.exports = function () {
var config = {
allTs:'./src/**/*.ts',
typeings:'./typings/**/*.ts',
server:'./server.ts',
tsOutPutPath:'./app',
allNgTs:'./client/**/*.ts',
ngOut:'./public/scripts/src'
};
return config;
}
here is my gulp task
gulp.task('compile-ng', function () {
var sourceTsFiles = [
config.typeings,
config.allNgTs
]
del(['public/scripts/**/*.js','public/scripts/**/*.html']).then(paths => {
console.log('Deleted files and folders:\n', paths.join('\n'));
});
var tsResult = gulp
.src(sourceTsFiles)
.pipe(sourcemaps.init())
.pipe(tsc(tsProject));
return tsResult.js
.pipe(sourcemaps.write('../map'))
.pipe(gulp.dest(config.ngOut));
});
Your tsconfig.json file should exclude node_modules and any d.ts files that may conflict with angular d.ts i.e:
{
"compilerOptions": {
"target": "ES5",
"module": "system",
"moduleResolution": "node",
"sourceMap": true,
"emitDecoratorMetadata": true,
"experimentalDecorators": true,
"removeComments": false,
"noImplicitAny": false
},
"exclude":[
"fonts",
"images",
"img",
"libs",
"navigation",
"node_modules",
"pagehtmls",
"typings"
]
}
Add ngTypeings:'./node_modules/angular2/typings/**/*.ts', to gulp.config.json file and use this angular2 typing in task instead of typeings
var sourceTsFiles = [
config.ngTypeings,
config.allNgTs
]