Where and how do typescript files become JS files in my project?

Viewed 8002

I'm working on an MVC React project on Visual Studio.

Everything so far has been fine, but now I have a typescript file I've written myself, which I want to be able to use in the project. It's something of a learning process for me, so for now I just want to be able to use that Typescript in a generic HTML page (not React) via standard <script src=...> tags.

I understand it needs to be compiled to JS, but I don't know how to set that process up.

I've found and tried a lot of solutions involving webpack.config.ts, package.json, tsconfig.json, etc, but nothing ever works.

Is there a definitive and obvious way to do this? Or is there something specific about my project that I've got wrong?

If it helps, here's how the file layout looks in my project (webGL.ts is the one I'm wanting to deal with).

enter image description here

I've tried adding this to tsconfig.json:

"files": [
    "/ClientApp/webGL.ts"
 ]

My webpack.config.js file looks like this:

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.tsx' },
        resolve: {
            extensions: ['.js', '.jsx', '.ts', '.tsx']
        },
        output: {
            path: path.join(__dirname, bundleOutputDir),
            filename: '[name].js',
            publicPath: 'dist/'
        },
        module: {
            rules: [
                { test: /\.tsx?$/, include: /ClientApp/, use: 'awesome-typescript-loader?silent=true' },
                { 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' },
                {
                    //for reading font files
                    test: /\.(woff|woff2|ttf|eot|ico)$/,
                    loader: 'file-loader?name=assets/[name].[hash].[ext]'
                }
            ]
        },
        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 suspect there's something I need to know or change in that file, but I'm a bit lost overall.

Any help much appreciated, thanks.

Update:

I also tried manually creating a JS file of the same name, with which I would manually copy TS into it and adjust as needed (I'm not actually trying to learn TS here, I'm trying to learn webGL and three.js, and would just prefer to do it via TS if I can).

After making the JS file, it was automatically placed as a stub under the TS file, like so:

enter image description here

I feel like this has some amount of relevance, but I don't know how or why. The fact that they've been automatically joined tells me something. I still don't know how to get it working in the project though..!

2 Answers

Generally, you write typescript in your src directory, create a tsconfig.json file with your compiler settings, and then use tsc to compile into javascript on another directory.

I have recently created a basic typescript starter project in github that you can check for reference.

In the tsconfig.json you can see that the code goes into the src directory, and the generated javascript goes into dist.

This repository uses tsc to compile via npm run build, but you can also use webpack, especially if you are compiling a project with multiple files for web, or if you want to use other transpilers like babel, etc.

example tsconfig.json

{
  "compilerOptions": {
    "module": "commonjs",
    "target": "es2018",
    "sourceMap": true,
    "outDir": "dist",
    "strict": true,
  },
  "include": [
    "src/**/*.ts"
  ],
  "exclude": [
    "node_modules",
    "**/node_modules/*"
  ]
}

In your project

In your specific use case, you are using webpack to transpile source files into javascript. Your webpack.config.js tells webpack how to do it. It is generating main.js in your dist directory (see entries in your config, and documentation for entry points).

If what you want is to add a new file into the existing project then you will need to add a new entry:

module.exports = {
  entry: {
    main: './ClientApp/boot.tsx',
    webGL: './ClientApp/webGL.tsx'
  }
};

this tells webpack to build 2 separate files with all dependencies bundled in each of them, one for your main app, and one for your webGL file.

Found the solution inside this seemingly unrelated tutorial: https://github.com/Microsoft/TypeScript-React-Conversion-Guide

I needed to update the entry part of webpack.config.js, like so:

        entry: {
            'main': './ClientApp/boot.tsx',
            'webGL': './ClientApp/webGL.ts'
        },
        resolve: {
            extensions: ['.js', '.jsx', '.ts', '.tsx']
        },
        output: {
            path: path.join(__dirname, bundleOutputDir),
            filename: '[name].js',
            publicPath: 'dist/'
        },

The name webGL is the name that will be given to the compiled TS file, which is then fed and processed according to the rules set out in the output section.

This can be referenced as required in HTML tags via:

<script src="~/dist/webGL.js" ></script>

Related