Search code examples
angularwebpackopera

Angular 2 plain js vs webpack / systemjs


We are testing suitability of Angular 2 on the Opera presto platform (12.51).

I'm very new to Angular 2 and webpack so its more than likely I have missed something obvious or there is a flaw in my understanding / assumptions.

I've noticed if I follow this tutorial:

https://angular.io/docs/js/latest/quickstart.html

The application loads and runs correctly.

But if I try to use the TypeScript version of the tutorial: https://angular.io/docs/ts/latest/quickstart.html

The application fails to load without any error.

So I did a bit of research and came to the conclusion that SystemJs is well outside of the browsers abilities.

After that I thought I would try webpack. so everything is dished up to the browser with nicely linked and packed files and there wasn't any dynamic module loading going on.

But the web pack version throws an error:

Uncaught exception: TypeError: Cannot convert 'core_1.ViewEncapsulation' to   object
  Error thrown at line 36, column 4 in <anonymous function>():
  ViewEncapsulationEnum.Emulated = ViewEncapsulationEnum.fromValue(core_1.ViewEncapsulation.Emulated);
called from line 30, column 0 in <anonymous function>():
var ViewEncapsulationEnum = (function () {
called from line 1371, column 1 in <anonymous function>(module, exports, __webpack_require__) in http://localhost:5000/vendor.js:
eval("\"use strict\";\nvar core_1 = __webpack_require__(79);\nvar core_private_1 = __webpack_require__(252);\nvar compile_metadata_1 = __webpack_require__(271);\nvar lang_1 = __webpack_require__(250);\nvar identifiers_1 = __webpack_require__(270);\nvar o = __webpack_require__(276);\nfunction _enumExpression(classIdentifier, value) {\n    if (lang_1.isBlank(value))\n        return o.NULL_EXPR;\n    var name = lang_1.resolveEnumToken(classIdentifier.runtime, value);\n    return o.importExpr(new compile_metadata_1.CompileIdentifierMetadata({\n        name: classIdentifier.name + \".\" + name,\n        moduleUrl: classIdentifier.moduleUrl,\n        runtime: value\n    }));\n}\nvar ViewTypeEnum = (function () {\n    function ViewTypeEnum() {\n    }\n    ViewTypeEnum.fromValue = function (value) {\n        return _enumExpression(identifiers_1.Identifiers.ViewType, value);\n    };\n    ViewTypeEnum.HOST = ViewTypeEnum.fromValue(core_private_1.ViewType.HOST);\n    ViewTypeEnum.COMPONENT = ViewTypeEnum.fromValue(core_private_1.ViewType.COMPONENT);\n    ViewTypeEnum.EMBEDDED = ViewTypeEnum.fromValue(core_private_1.ViewType.EMBEDDED);\n    return ViewTypeEnum;\n}());\nexports.ViewTypeEnum = ViewTypeEnum;\nvar 

My understanding was that web pack would resolve all of the dependencies together and bundle them up.

Any ideas why I would get an error with web pack that I don't get with plain JS?

webpack.common.js

var webpack = require('webpack');
var HtmlWebpackPlugin = require('html-webpack-plugin');
var ExtractTextPlugin = require('extract-text-webpack-plugin');
var helpers = require('./helpers');

module.exports = {
  entry: {
    'polyfills': './src/polyfills.ts',
    'vendor': './src/vendor.ts',
    'app': './src/main.ts'
  },

  resolve: {
    extensions: ['', '.js', '.ts']
  },

  module: {
    loaders: [
      {
        test: /\.ts$/,
        loader: 'ts'
      },
      {
        test: /\.html$/,
        loader: 'html'
      },
      {
        test: /\.(png|jpe?g|gif|svg|woff|woff2|ttf|eot|ico)$/,
        loader: 'file?name=assets/[name].[hash].[ext]'
      },
      {
        test: /\.css$/,
        exclude: helpers.root('src', 'app'),
        loader: ExtractTextPlugin.extract('style', 'css?sourceMap')
      },
      {
        test: /\.css$/,
        include: helpers.root('src', 'app'),
        loader: 'raw'
      }
    ]
  },

  plugins: [
    new webpack.optimize.CommonsChunkPlugin({
      name: ['app', 'vendor', 'polyfills']
    }),

    new HtmlWebpackPlugin({
      template: 'src/index.html'
    })
  ]
};

webpack.dev.js

var webpackMerge = require('webpack-merge');
var ExtractTextPlugin = require('extract-text-webpack-plugin');
var commonConfig = require('./webpack.common.js');
var helpers = require('./helpers');

module.exports = webpackMerge(commonConfig, {
  devtool: 'cheap-module-eval-source-map',

  output: {
    path: helpers.root('dist'),
    publicPath: 'http://localhost:5000/',
    filename: '[name].js',
    chunkFilename: '[id].chunk.js'
  },

  plugins: [
    new ExtractTextPlugin('[name].css')
  ],

  devServer: {
    historyApiFallback: true,
    stats: 'minimal'
  }
});

tsconfig.json

{
  "compilerOptions": {
    "target": "es5",
    "module": "commonjs",
    "moduleResolution": "node",
    "sourceMap": true,
    "emitDecoratorMetadata": true,
    "experimentalDecorators": true,
    "removeComments": false,
    "noImplicitAny": true,
    "suppressImplicitAnyIndexErrors": true
  }
}

typings.json

{
  "globalDependencies": {
    "core-js": "registry:dt/core-js#0.0.0+20160317120654",
    "jasmine": "registry:dt/jasmine#2.2.0+20160505161446",
    "node": "registry:dt/node#6.0.0+20160613154055"
  },
}

Solution

  • We ended up using Backbone.js. It was far more compatible with Presto and performed better on the lower end CPU devices.

    Additionally with Angular dropping support for the earlier opera browsers it just made sense from a future proofing point of view.

    We are really happy with the result.