3

I'm building a knockoutJs project using Typescript and Webpack, and I'm hitting a very weird issue.

The module that webpack is failing on is this:

import esPlayerVM from "./components/es-player";
import esPlayerTemplate from "./components/es-player.tmpl.html";
import fsButtonVm from "./components/fullscreen-button";
import fsButtonHtml from "./components/fullscreen-button.tmpl.html";


export default class Registrator {

    static Register() {
        var koComp = (elName: string, vm: any, html: string) => {
            ko.components.register(elName, { viewModel: vm, template: html });
        }

        koComp('es-player', esPlayerVM, esPlayerTemplate);
        koComp('fullscreen-button', fsButtonVm, fsButtonHtml);
        //ko.components.register('es-player', { viewModel: esPlayerVM, template: esPlayerTemplate });
        //this.RegisterComponent('fullscreen-button', fsButtonVm, fsButtonHtml);
    }
}

Webpack outputs this:

ERROR in ./ComponentRegistration.ts
Module parse failed: C:\Users\Marlon\Documents\Projects\eps-ko\src\ComponentRegistration.ts Unexpected token (10:28)
You may need an appropriate loader to handle this file type.
|
|     static Register() {
|         var koComp = (elName: string, vm: any, html: string) => {
|             ko.components.register(elName, { viewModel: vm, template: html });
|         }
 @ ./Main.ts 16:0-50

If I remove the koComp varable, and directly register the component in the Register method, webpack is happy. Originally I had a private static function as you can see from the bottom comment, but webpack had the same problem with that.

I have googled, and others are getting this when typescript is outputting es2016 code, so they have to pass it through babel, however I am targetting es5 so I would expect mine to be fine? I am not using any react stuff like .tsx files either.

I've used both ts-loader and awesome-typescript-loader, both have the same error.

Here is my tsconfig.json

{
    "compilerOptions": {
        "allowSyntheticDefaultImports": true,
        "module": "es2015",
        "target": "es5",
        "moduleResolution": "node",
        "noImplicitAny": true,
        "sourceMap": false,
        "importHelpers": true
    }
}

Originally I hade modules set to commonjs, but when trying ts-loader I followed their example.

Here is my webpack.config:

const path = require('path');
const webpack = require('webpack');

const ExtractTextPlugin = require('extract-text-webpack-plugin');
const { CheckerPlugin } = require('awesome-typescript-loader')

// Create multiple instances
const extractCSS = new ExtractTextPlugin('es-player.bundle.css');

module.exports = {
  context: path.resolve(__dirname, './src'),
  entry: {
    app: './Main.ts',
  },
  output: {
    path: path.resolve(__dirname, './dist'),
    filename: 'es-player.bundle.js',
  },
  //devtool: "cheap-eval-source-map",
  resolve: {
    extensions: ['.ts', '.tsx']
  },    
  module: {
    loaders: [
      {
        test: /\.tsx?$/,
        exclude: /node_modules/,
        loader: 'ts-loader'
      }
    ],
    rules: [
      {
        test: /\.css$/,
        use: extractCSS.extract([ 'css-loader', 'postcss-loader' ])
      },
      {
        test: /\.less$/i,
        use: extractCSS.extract([ 'css-loader', 'less-loader', 'postcss-loader' ])
      },
      {
        test: /\.tmpl.html?$/,
        use: 'raw-loader'
      }
    ]
  },
  plugins: [
    extractCSS
    //new CheckerPlugin()
  ],
};

Versions:

Typescript: 2.2.2
Webpack: 2.3.3
awesome-typescript-loader: 3.1.2
ts-loader: 2.0.3

I could just register them directly, but I am wondering what is happening that is causing this error.

edit

After digging and deleting code, it seems webpack is failing if any exported module has typed parameters on any method etc. This is really wierd as I thought webpack was working with the transpiled javascript generated from the loaders? This infers it is trying to work with the raw .ts files.

1 Answer 1

5

TL:DR The use of both loaders and rules sections is not supported by WebPack - must use one or the other.

After hours of debugging, it was due to having the typescript loader defined in the loaders section of the webpack.config.js file. Moving it into the rules section fixed the issue.

Amended webpack.config.js file looks like this:

const path = require('path');
const ExtractTextPlugin = require('extract-text-webpack-plugin');
const { CheckerPlugin } = require('awesome-typescript-loader')

const extractCSS = new ExtractTextPlugin('es-player.bundle.css');

module.exports = {
  context: path.resolve(__dirname, './src'),
  entry: {
    app: './Main.ts',
  },
  output: {
    path: path.resolve(__dirname, './dist'),
    filename: 'es-player.bundle.js',
  },
  //devtool: "cheap-eval-source-map",
  resolve: {
    extensions: ['.js', '.ts', '.tsx']
  },    
  module: {
    rules: [
      {
        test: /\.css$/,
        use: extractCSS.extract([ 'css-loader', 'postcss-loader' ])
      },
      {
        test: /\.less$/i,
        use: extractCSS.extract([ 'css-loader', 'less-loader', 'postcss-loader' ])
      },
      {
        test: /\.tmpl.html?$/,
        use: 'raw-loader'
      },
      {
        test: /\.tsx?$/,
        exclude: /node_modules/,
        loader: 'awesome-typescript-loader'
      }
    ]
  },
  plugins: [
    extractCSS,
    new CheckerPlugin()
  ],
};

Both ts-loader and the at-loader state to define them in the loaders sections on their respective github pages. But the Webpack 2 docs state to put them in the rules section. Very confusing to say the least.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.