Ts-loader: Problem with TSX

Created on 10 Sep 2015  路  18Comments  路  Source: TypeStrong/ts-loader

Hi, thanks for the great and updated ts-loader.
I seem to be struggling with the "*.tsx" files, for which I keed receiving following error:

ERROR in ../app/components/router.tsx
Module parse failed: /Users/tomi/Documents/Programming/Github/meteor-webpack-react/node_modules/ts-loader/index.js!/Users/tomi/Documents/Programming/Github/meteor-webpack-react/app/components/router.tsx Line 1: Unexpected token
You may need an appropriate loader to handle this file type.
| import { BlogHome } from './blog/blog';
| import ReactLayout from './react-layout';
| //console.log(BlogHome);
 @ ../app/main_client.js 15:0-30

This is my config:

resolve: {
    extensions: ['', '.js', '.jsx', '.ts', '.tsx' ],
    alias: {
      app: path.join(__dirname, '../app'),
    },
  },
  module: {
    loaders: [
      {
        test: /\.jsx?$/,
        loader: 'babel?stage=0',
        exclude: /node_modules|lib/,
      },
      {
        test: /\.css$/,
        loader: 'style-loader!css-loader'
      },
      {
        test: /(\.png|\.eot|\.svg|\.woff|\.ttf)/,
        loader: 'file'
      },
      // all files with a `.ts` or `.tsx` extension will be handled by `ts-loader`
      {
        test: /\.ts(x?)$/,
        loader: 'ts-loader'
      }
    ],

Typescript installed is 1.6.0 beta.

Would you know what the problem can be?
Thanks!

question

Most helpful comment

install awesome-typescript-loader. Add in webpack.config.js:

...
        loaders: [
            {
                test: /\.tsx?$/,
                loaders: [
                    'react-hot-loader',
                    'awesome-typescript-loader'
                ],
                include: path.join(__dirname, 'src')
            }
        ]

All 18 comments

Yup. Basically you've got TypeScript configured to output ES6 which webpack doesn't understand. You should either configure TypeScript to target ES5 or run Babel after ts-loader, like loader: 'babel!ts'.

Detailed info can be found here: http://www.jbrantly.com/es6-modules-with-typescript-and-webpack/

But I do have babel configured, would you please check if correctly?

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

module.exports = {
  devtool: 'source-map',
  entry: [
    '../lib/core-js-no-number',
    'regenerator/runtime',
    '../app/main_client',
  ],
  output: {
    path: path.join(__dirname, 'assets'),
    filename: 'client.bundle.js',
    publicPath: '/assets/',
  },
  resolve: {
    extensions: ['', '.js', '.jsx' ],
    alias: {
      app: path.join(__dirname, '../app'),
    },
  },
  module: {
    loaders: [
      {
        test: /\.jsx?$/,
        loader: 'babel?stage=0',
        exclude: /node_modules|lib/,
      },
      {
        test: /\.css$/,
        loader: 'style-loader!css-loader'
      },
      {
        test: /(\.png|\.eot|\.svg|\.woff|\.ttf)/,
        loader: 'file'
      },
      // all files with a `.ts` or `.tsx` extension will be handled by `ts-loader`
      {
        test: /\.ts(x?)$/,
        loader: 'ts-loader?compiler=ntypescript&+useCache&+useBabel&module=common&jsx=preserve'
      }
    ],
    ts: {
      compiler: 'ntypescript'
    }
  },
  plugins: [
    new webpack.PrefetchPlugin("react"),
    new webpack.PrefetchPlugin("react/lib/ReactComponentBrowserEnvironment")
  ]
};

DONE. Sorry.. your web page was very informative. Thanks!

Hi, as you mention in your blogpost following configuration makes the loader work:

{
        test: /\.tsx?$/,
        loader: 'babel!ts-loader'
      }

BUT

it disables the hot-code-reload :(

I tried to enable the output to ES5 so that I omit the babel step to see if it works, but then, suddenly it stops processing TSX files with a following error:

ERROR in ../app/components/App.tsx
Module parse failed: /Users/tomi/Documents/Programming/Github/meteor-webpack-react-tomi/node_modules/ts-loader/index.js!/Users/tomi/Documents/Programming/Github/meteor-webpack-react-tomi/app/components/App.tsx Line 27: Unexpected token <
You may need an appropriate loader to handle this file type.
|     };
|     PostsView.prototype.render = function () {
|         return (<div className="App">
|         <blaze_template_1.default template={Template["loginButtons"]}/>
|         <h1>Hello Webpack!</h1>
 @ ../app/main_client.js 13:21-48

Any idea? THANKS!

it disables the hot-code-reload :(

@tomitrescak is you mean React Hot Loader, you need to enable loose mod for Babel and it will work.

Thanks a lot for your response! How do I do that?

@tomitrescak the easiest way is to write babel?loose=all!ts-loader

Nope ;( Still getting: [HMR] The following modules couldn't be hot updated: (They would need a full reload!)

I tried to enable the output to ES5 so that I omit the babel step to see if it works, but then, suddenly it stops processing TSX files with a following error

In this case you were using Babel to transform JSX. If you remove Babel then you need TypeScript to transform the JSX by using the "react" value for the jsx option instead of "preserve".

Still getting: [HMR] The following modules couldn't be hot updated: (They would need a full reload!)

This sounds like you're not accepting the modules. Remember that hot module replacement is an _opt-in_ mechanism. By default modules will not be hot reloaded even if you've enabled the HMR plugin, etc. You have to manually enable by calling "module.hot.accept()" in your entry point (as a super simple example, it can get more complicated). See http://webpack.github.io/docs/hot-module-replacement.html for more information.

@tomitrescak I'm having the same issue. Did you ever get this working as desired?

I'm getting this problem still

tsconfig.json

{
  "compilerOptions": {
    "module": "commonjs",
    "noImplicitAny": false,
    "removeComments": false,
    "preserveConstEnums": true,
    "sourceMap": true,
    "target": "es5",
    "allowJs": true,
    "declaration": true,
    "jsx": "react",
    "pretty": true
  }
}

webpack.config.js

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

module.exports = {
  entry:     {
    app:    [
      path.join(__dirname, 'app/consumer-web.tsx')
    ], lib: [
      'react',
      'react-router',
      'react-googlemaps',
      'react-bootstrap',
      "moment",
      "moment-timezone",
      "intl-tel-input",
      "jquery.payment",
      "slick-carousel",
      "jed",
      "po2json"
    ]
  },
  output: {
    path: path.join(__dirname, 'dist'),
    filename: "app.js",
    chunkFilename: "[name].js"
  },
  resolve: {
    // Add '.ts' and '.tsx' as a resolvable extension.
    extensions: ["", ".webpack.js", ".web.js", ".ts", ".tsx", ".js"]
  },
  loaders: [
    {test: /\.tsx?$/, loader: "ts-loader"},
    {test: /\.json?$/, loader: 'json-loader'}
  ],
  plugins: [
    new webpack.optimize.CommonsChunkPlugin(/* chunkName= */"lib", /* filename= */"lib.js", Infinity)
  ],
  externals: ['jquery']
};

Running

node_modules/.bin/webpack --config webpack.config.js --progress --colors --display-error-details

Result:

ERROR in ./app/consumer-web.tsx
Module parse failed: /Users/dmitriid/Projects/keyflow/keyflow-website/src/static/campaign/js/app/consumer-web.tsx 

Unexpected token (160:73)

You may need an appropriate loader to handle this file type.

Maybe it doesn't pick up tsconfig.json? How would I check that?

I did the same mistake. The "loaders" section should be inside "module" section

Instead of

{
loaders: []
}

You should use

{
module: {
loader: []
}
}

install awesome-typescript-loader. Add in webpack.config.js:

...
        loaders: [
            {
                test: /\.tsx?$/,
                loaders: [
                    'react-hot-loader',
                    'awesome-typescript-loader'
                ],
                include: path.join(__dirname, 'src')
            }
        ]

The thing that fixed this issue for me was making sure I had "module": "commonjs" set in my tsconfig.json file (or the webpack config object). That's using either awesome-typescript-loader or ts-loader, if the module is set to "es6" then webpack won't read it. The other alternative is to run babel after the typescript loader

Tried all of this and nothing helped. Can someone look at my config and try to figure it out please?

webpack.config

'use strict';
module.exports = function(config) {
  config.set({
    basePath: '',
    frameworks: ['jasmine'],
    reporters: ['progress'],
    port: 9876,
    colors: false,
    autoWatch: true,
    browsers: ['Chrome', 'Firefox'],
    singleRun: false,

    files: [
      './src/*.js',
      './tests/unit/*.js'],

    webpackMiddleware: {
      noInfo: true
    },
      test: /\.(ts|tsx)?$/,
    module: {
      loader: 'ts-loader',
      include: __dirname
    }

    });
};

karma config:

const webpack = require('./webpack.config');
// Karma configuration
// Generated on Sun Dec 09 2018 00:24:16 GMT+0100 (GMT+01:00)

module.exports = function(config) {
  config.set({

    // base path that will be used to resolve all patterns (eg. files, exclude)
    basePath: '',


    // frameworks to use
    // available frameworks: https://npmjs.org/browse/keyword/karma-adapter
    frameworks: ['jasmine'],


    // list of files / patterns to load in the browser
    files: [
      'tests/unit/*.spec.ts',
    ],


    // list of files / patterns to exclude
    exclude: [
    ],

    // preprocess matching files before serving them to the browser
    // available preprocessors: https://npmjs.org/browse/keyword/karma-preprocessor
    preprocessors: {
      './src/*.ts': ['webpack'],
      './tests/unit/*.spec.ts': ['webpack']
    },

    webpack: {
            // you don't need to specify the entry option because
            // karma watches the test entry points
            // webpack watches dependencies

      // ... remainder of webpack configuration (or import)
      mode: 'production',
    },

    webpackMiddleware: {
      // webpack-dev-middleware configuration
      // i. e.
      stats: 'errors-only'
    },


    // test results reporter to use
    // possible values: 'dots', 'progress'
    // available reporters: https://npmjs.org/browse/keyword/karma-reporter
    reporters: ['progress'],


    // web server port
    port: 9876,


    // enable / disable colors in the output (reporters and logs)
    colors: true,


    // level of logging
    // possible values: config.LOG_DISABLE || config.LOG_ERROR || config.LOG_WARN || config.LOG_INFO || config.LOG_DEBUG
    logLevel: config.LOG_INFO,


    // enable / disable watching file and executing tests whenever any file changes
    autoWatch: true,


    // start these browsers
    // available browser launchers: https://npmjs.org/browse/keyword/karma-launcher
    browsers: ['Chrome', 'Firefox'],


    // Continuous Integration mode
    // if true, Karma captures browsers, runs the tests and exits
    singleRun: false,

    // Concurrency level
    // how many browser should be started simultaneous
    concurrency: Infinity,

    plugins: [
      'karma-jasmine',
      'karma-webpack',
      'karma-spec-reporter',
      'karma-chrome-launcher',
      'karma-firefox-launcher',
      'karma-sourcemap-writer',
      'karma-sourcemap-loader',
      'awesome-typescript-loader'
    ],

  })
}

package.json:

{
  "name": "js-todo",
  "version": "1.0.0",
  "description": "JS based to-do list",
  "main": "src/main.js",
  "scripts": {
    "start": "localhost 'src' -p 8808",
    "wd": "webdriver-manager update && webdriver-manager start",
    "wd-update": "webdriver-manager update",
    "test": "protractor tests/e2e/conf.js",
    "build": "babel src -d lib",
    "lint": "tslint --config tslint.json --project ./",
    "lint-fix": "tslint --config tslint.json --project ./ --fix"
  },
  "repository": {
    "type": "git",
    "url": "git+https://github.com/vivacenontroppo/js-todo.git"
  },
  "author": "Marian Kucharski",
  "license": "ISC",
  "bugs": {
    "url": "https://github.com/vivacenontroppo/js-todo/issues"
  },
  "homepage": "https://github.com/vivacenontroppo/js-todo#readme",
  "devDependencies": {
    "awesome-typescript-loader": "^5.2.1",
    "babel-cli": "^6.26.0",
    "babel-preset-env": "^1.7.0",
    "babel-preset-es2015": "^6.24.1",
    "concurrently": "^4.1.0",
    "jasmine": "^3.3.1",
    "jasmine-core": "^3.3.0",
    "jasminewd2": "^2.2.0",
    "karma": "^3.1.3",
    "karma-chrome-launcher": "^2.2.0",
    "karma-firefox-launcher": "^1.1.0",
    "karma-jasmine": "^2.0.1",
    "karma-sourcemap-loader": "^0.3.7",
    "karma-sourcemap-writer": "^0.1.2",
    "karma-spec-reporter": "0.0.32",
    "karma-webpack": "^3.0.5",
    "localhost": "^0.2.3",
    "ts-loader":^5.3.1",
    "tslint": "^5.11.0",
    "typescript": "^3.2.2"
  },
  "dependencies": {
    "@types/jasmine": "^3.3.0",
    "@types/protractor": "4.0.0",
    "@types/selenium-webdriver": "^3.0.13",
    "protractor": "^5.4.1",
    "selenium": "^2.20.0",
    "webdriver": "^5.0.0-alpha.7",
    "webdriver-manager": "^12.1.0",
    "protractor-jasmine2-screenshot-reporter": "^0.5.0",
    "webpack": "^4.27.1",
    "webpack-cli": "^3.1.2"
  }
}

tsconfig:

{
    "compilerOptions": {
      "jsx": "react",
      "target": "es5",
      "module": "commonjs",
      "moduleResolution": "node",
      "sourceMap": true,
      "emitDecoratorMetadata": true,
      "experimentalDecorators": true,
      "removeComments": false,
      "noImplicitAny": false,
      "noUnusedLocals": true,
      "noUnusedParameters": true,
      "typeRoots": [
        "./node_modules/@types/"
      ],
      "lib": [
        "es2015"
      ]
    },
    "compileOnSave": true,
    "exclude": [
      "node_modules/*",
      "**/*-aot.ts"
    ],
  }

actuall spec (the string type on title is braking compilation):

import { Task } from '../../src/task.class';
import { TasksList } from '../../src/tasks-list.class';

describe('test task class;', () => {

    const task = function (title: **string**, priority, isChecked,){
        return new Task(title, priority, isChecked)
     };

    //const tasksList = new TasksList(null, null, null, null, null, null, [])

    it('create an instance of task', () => {
        const taskOne = task('title', 1, false);
        expect(taskOne.title).toBe('title');
        expect(taskOne.priority).toBe(1);
        expect(taskOne.isChecked).toBe(false);
        taskOne.toggleCheck();
        expect(taskOne.isChecked).toBe(true);
    });
    it('change some parameters of the task', () => {

        const taskTwo = task('string2', 4, true);
        expect(taskTwo.title).toBe('string2');
    });
});

Please, anyone, help me! : (

Of course as you can see I have added some things that were mention here, but maybe I should delete for now, until someone figures it out...

Ok, so I did manage to figure it out. I checked and I was pointing to .ts files in webpack and karma configs, which is stupid because I use typescript compiler and then running tests from the .js files. So I changed that to .js in configs, deleted all the unnecessary stuff from typescript in configs and it works!

Was this page helpful?
0 / 5 - 0 ratings