Javascriptservices: Do we have to use TypeScript?

Created on 24 Oct 2017  路  17Comments  路  Source: aspnet/JavaScriptServices

With VS 2017 when creating a React.js app, default files are .tsx. For those who don't want to work with TypeScript, is there an option to bootstrap with .jsx files? Is it possible to create a React.js app with ES6 or plain JS?

I couldn't find any info about this and there are some other people that have asked about it on Internet but with no answers.

Most helpful comment

Sorry for the late response, got busy.

  1. Delete route.tsx and all the components in the 'components' directory
  2. Rename 'boot.tsx' to 'boot.jsx' and remove any TypeScript features in the file. Make 'boot.jsx' return a simple <h1>Hello World!</h1>.
  3. Go to 'webpack.config.js' and redirect entry to 'boot.jsx' as we renamed it.
  4. In 'webpack.config.js' remove the rule related to '.tsx' and add the following rule in 'rules' section to handle JS and JSX file compilation:
{
    test: /\.js/,
    use: [{
        loader: 'babel-loader',
        options: {
            presets: ["env", "react"]
        }
    }],
    exclude: /node_modules/
}
  1. Fire up a terminal (command prompt), go to your project directory (not the solution directory), install following packages: babel-core, babel-loader, babel-preset-env, babel-preset-react like this:
    yarn add babel-core babel-loader babel-preset-env babel-preset-react

Try and run your application, typically in VS 2017 and it should run fine.

All 17 comments

There isn't an option, but there are only a few files in by default, so it won't take too long if you want to rename them to .jsx and remove the TypeScript type annotations.

I tried to convert files from .tsx to .jsx, removed all the components and created a new one as Home.jsx, simply returning a <h1>Message</h1>. I am getting this error (I'm not an experienced JS developer, so I may have missed something very basic here):

ERROR in ./ClientApp/boot.jsx
Module parse failed: c:\users\mert\documents\visual studio 2017\Projects\ReactJsx\ReactJsx\ClientApp\boot.jsx Unexpected token (13:81)
You may need an appropriate loader to handle this file type.
|     // This code starts up the React app when it runs in a browser. It sets up the routing
|     // configuration and injects the app into a DOM element.
|     const baseUrl = document.getElementsByTagName('base')[0].getAttribute('href')!;
|     ReactDOM.render(
|         <AppContainer>
 @ multi react-hot-loader/patch event-source-polyfill webpack-hot-middleware/client?path=__webpack_hmr&dynamicPublicPath=true ./ClientApp/boot.jsx

boot.jsx is:

import './css/site.css';
import 'bootstrap';
import * as React from 'react';
import * as ReactDOM from 'react-dom';
import { AppContainer } from 'react-hot-loader';
import { BrowserRouter } from 'react-router-dom';
import * as RoutesModule from './routes';
let routes = RoutesModule.routes;

function renderApp() {
    // This code starts up the React app when it runs in a browser. It sets up the routing
    // configuration and injects the app into a DOM element.
    const baseUrl = document.getElementsByTagName('base')[0].getAttribute('href')!;
    ReactDOM.render(
        <AppContainer>
            <BrowserRouter children={ routes } basename={ baseUrl } />
        </AppContainer>,
        document.getElementById('react-app')
    );
}

renderApp();

// Allow Hot Module Replacement
if (module.hot) {
    module.hot.accept('./routes', () => {
        routes = require('./routes').routes;
        renderApp();
    });
}

Okay, I used Babel to see what's wrong with the code above and I removed ! from the end of ...getAttribute('href');, I don't know what ! does but Babel compiled the file successfully but I still get the same error when I start the application:

ERROR in ./ClientApp/boot.jsx
Module parse failed: c:\users\mert\documents\visual studio 2017\Projects\ReactJsx\ReactJsx\ClientApp\boot.jsx Unexpected token (15:8)
You may need an appropriate loader to handle this file type.
|     const baseUrl = document.getElementsByTagName('base')[0].getAttribute('href');
|     ReactDOM.render(
|         <AppContainer>
|             <BrowserRouter children={ routes } basename={ baseUrl } />
|         </AppContainer>,
 @ multi react-hot-loader/patch event-source-polyfill webpack-hot-middleware/client?path=__webpack_hmr&dynamicPublicPath=true ./ClientApp/boot.jsx

You may need an appropriate loader to handle this file type means that Webpack doesn't know what you want it to do with the jsx files. Try adding something like jsx-loader (https://github.com/petehunt/jsx-loader) or babel-loader (https://www.twilio.com/blog/2015/08/setting-up-react-for-es6-with-webpack-and-babel-2.html).

I added babel-loader by running yarn add babel-loader babel-core babel-preset-env --dev in the project directory as specified here.

Then I modified webpack.config to add babel-loader rule and now it is:

const path = require('path');
const webpack = require('webpack');
const ExtractTextPlugin = require('extract-text-webpack-plugin');
const CheckerPlugin = require('awesome-typescript-loader').CheckerPlugin;
const bundleOutputDir = './wwwroot/dist';

module.exports = (env) => {
    const isDevBuild = !(env && env.prod);
    return [{
        stats: { modules: false },
        entry: { 'main': './ClientApp/boot.jsx' },
        resolve: { extensions: ['.js', '.jsx', '.ts', '.tsx'] },
        output: {
            path: path.join(__dirname, bundleOutputDir),
            filename: '[name].js',
            publicPath: 'dist/'
        },
        module: {
            rules: [
                {
                    test: /\.jsx$/,
                    include: /ClientApp/,
                    exclude: /(node_modules|bower_components)/,
                    use: {
                        loader: 'babel-loader',
                        options: {
                            presets: ['env', 'react']
                        }
                    }
                },
                { test: /\.js(x?)$/, include: /ClientApp/, use: 'babel-loader' },
                { test: /\.css$/, use: isDevBuild ? ['style-loader', 'css-loader'] : ExtractTextPlugin.extract({ use: 'css-loader?minimize' }) },
                { test: /\.(png|jpg|jpeg|gif|svg)$/, use: 'url-loader?limit=25000' }
            ]
        },
        plugins: [
            new CheckerPlugin(),
            new webpack.DllReferencePlugin({
                context: __dirname,
                manifest: require('./wwwroot/dist/vendor-manifest.json')
            })
        ].concat(isDevBuild ? [
            // Plugins that apply in development builds only
            new webpack.SourceMapDevToolPlugin({
                filename: '[file].map', // Remove this line if you prefer inline source maps
                moduleFilenameTemplate: path.relative(bundleOutputDir, '[resourcePath]') // Point sourcemap entries to the original file locations on disk
            })
        ] : [
                // Plugins that apply in production builds only
                new webpack.optimize.UglifyJsPlugin(),
                new ExtractTextPlugin('site.css')
            ])
    }];
};

I'm still getting this error:

ERROR in ./ClientApp/boot.jsx
Module parse failed: C:\Users\mert\Documents\Visual Studio 2017\Projects\WebApplication6\WebApplication6\ClientApp\boot.jsx Unexpected token (13:8)
You may need an appropriate loader to handle this file type.
|     const baseUrl = document.getElementsByTagName('base')[0].getAttribute('href');
|     ReactDOM.render(
|         <AppContainer>
|             <BrowserRouter children={ routes } basename={ baseUrl } />
|         </AppContainer>,
 @ multi react-hot-loader/patch event-source-polyfill webpack-hot-middleware/client?path=__webpack_hmr&dynamicPublicPath=true ./ClientApp/boot.jsx

Obviously I'm missing something here, can you elaborate more please? Is there any documentation or tutorial that I can follow?

Sorry, I'm not an expert on Babel - I'd recommend raising this with the Babel or Webpack communities.

I'm running into the same issue as you, @makcakaya . Did you ever get it sorted out?

@nvonbenken Yes, I managed to resolve it. I can share it here tomorrow.

@makcakaya Great, thanks.

@makcakaya Any update on this?

Sorry for the late response, got busy.

  1. Delete route.tsx and all the components in the 'components' directory
  2. Rename 'boot.tsx' to 'boot.jsx' and remove any TypeScript features in the file. Make 'boot.jsx' return a simple <h1>Hello World!</h1>.
  3. Go to 'webpack.config.js' and redirect entry to 'boot.jsx' as we renamed it.
  4. In 'webpack.config.js' remove the rule related to '.tsx' and add the following rule in 'rules' section to handle JS and JSX file compilation:
{
    test: /\.js/,
    use: [{
        loader: 'babel-loader',
        options: {
            presets: ["env", "react"]
        }
    }],
    exclude: /node_modules/
}
  1. Fire up a terminal (command prompt), go to your project directory (not the solution directory), install following packages: babel-core, babel-loader, babel-preset-env, babel-preset-react like this:
    yarn add babel-core babel-loader babel-preset-env babel-preset-react

Try and run your application, typically in VS 2017 and it should run fine.

Hi. Are you be able to figure out how to do it with react and redux?

Hi, sorry I didn't use Redux before. The steps I explained above should enable you to use React and ES6, adding Redux on top of that should be somewhat simple but I don't really know.

@makcakaya I just want to thank you from the bottom of my soul for this explanation. I spent an entire day fighting with TypeScript's BS. Using your guide I got rid of it in under 2 minutes.
You deserve a freaking medal

Can you share what your boot.jsx looks like? I can't seem to get hot module swapping working when switching from TypeScript.

@makcakaya I'm another person who encountered the same issues. Thank you so much. @nvonbenken it should look something like this... only difference is that I exchanged the "hello world" with an app component.

import './css/site.css';
import 'bootstrap';
import * as React from 'react';
import * as ReactDOM from 'react-dom';
import { AppContainer } from 'react-hot-loader';
import { BrowserRouter } from 'react-router-dom';
import App from './App';

ReactDOM.render(,document.getElementById('react-app'));

@makcakaya However I wasn't able how to work out how to compute properties syntax for css classNames ... e.g.

https://www.screencast.com/t/3wItif6Za1

Were you able to get this working? Many Thanks again :)

Was this page helpful?
0 / 5 - 0 ratings

Related issues

justinyoo picture justinyoo  路  3Comments

caesay picture caesay  路  3Comments

dantheman999301 picture dantheman999301  路  4Comments

benaadams picture benaadams  路  3Comments

natemcmaster picture natemcmaster  路  4Comments