ts-loader: TS18002 Error thrown when building prod package

Expected Behaviour

Should compile without errors

Actual Behaviour

Returns this error below. The interesting thing is that it is transient. The build sometimes succeeds with the success rate of ~50%

ERROR in [tsl] ERROR
      TS18002: The 'files' list in config file 'tsconfig.json' is empty.
 @ multi babel-polyfill whatwg-fetch ./infrastructure/webpackSetup.ts ./index.tsx main[2]

ERROR in ./infrastructure/webpackSetup.ts
Module build failed (from ./node_modules/ts-loader/index.js):
Error: error while parsing tsconfig.json

Steps to Reproduce the Problem

This is the config I use:

webpack.common.js:

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

const urlLoaderFileSizeLimit = 50000;
const svgOutputName = "svg/[name].[ext]";
const fontOutputName = "fonts/[name].[ext]";
const imageOutputName = "images/[name].[ext]";

process.traceDeprecation = true;

module.exports = {

    entry: [
        "babel-polyfill",
        "whatwg-fetch",
        path.join(__dirname, "infrastructure/webpackSetup.ts"),
        path.join(__dirname, "index.tsx"),
    ],

    output: {
        filename: "app.js",
        chunkFilename: "[name].[chunkhash].js",
        path: path.join(__dirname, "__dist__"),
    },

    resolve: {
        extensions: [".ts", ".tsx", ".js", ".jsx", ".json", ".css", ".scss", ".svg", ".woff", "woff2", ".ttf"]
    },

    module: {
        rules: [
            {
                test: /\.svg$/,
                loader: "svg-url-loader",
                options: {
                    limit: urlLoaderFileSizeLimit,
                    iesafe: true,
                    stripdeclarations: true,
                    name: svgOutputName,
                }
            },
            {
                test: /\.(woff|woff2)(\?v=\d+\.\d+\.\d+|\?\w+)?$/,
                loader: "url-loader",
                options: {
                    limit: urlLoaderFileSizeLimit,
                    mimetype: "application/font-woff",
                    name: fontOutputName,
                }
            },
            {
                test: /\.[ot]tf$/,
                loader: "url-loader",
                options: {
                    limit: urlLoaderFileSizeLimit,
                    mimetype: "application/octet-stream",
                    name: fontOutputName,
                }
            },
            {
                test: /\.eot$/,
                loader: "url-loader",
                options: {
                    limit: urlLoaderFileSizeLimit,
                    mimetype: "application/vnd.ms-fontobject",
                    name: fontOutputName,
                }
            },
            {
                test: /\.png$/,
                loader: "url-loader",
                options: {
                    limit: urlLoaderFileSizeLimit,
                    mimetype: "image/png",
                    name: imageOutputName,
                }
            },
            {
                test: /\.gif$/,
                loader: "url-loader",
                options: {
                    limit: urlLoaderFileSizeLimit,
                    mimetype: "image/gif",
                    name: imageOutputName,
                }
            },
        ]
    },

    plugins: [
        new webpack.NoEmitOnErrorsPlugin(),
    ],
};

webpack.prod.js:

const merge = require("webpack-merge");
const common = require("./webpack.common.js");
const webpack = require("webpack");
const ExtractTextPlugin = require("extract-text-webpack-plugin");
const ForkTsCheckerWebpackPlugin = require("fork-ts-checker-webpack-plugin");
const BundleAnalyzerPlugin = require("webpack-bundle-analyzer").BundleAnalyzerPlugin;

module.exports = merge.strategy({
    entry: "replace",
}
)(common, {

    mode: "production",

    optimization: {
        splitChunks: {
            cacheGroups: {
                vendors: {
                    test: /[\\/]node_modules[\\/]/,
                    name: "vendors",
                    chunks: "initial"
                },
            }
        }
    },

    module: {
        rules: [
            {
                test: /\.tsx?$/,
                loader: "ts-loader",
                options: { transpileOnly: true, configFile: "./tsconfig.prod.json" },
                exclude: /node_modules/,
            },
            {
                test: /\.s?css$/,
                use: ExtractTextPlugin.extract({
                    fallback: "style-loader",
                    use: ["css-loader", "sass-loader"],
                })
            }
        ]
    },

    plugins: [
        new ForkTsCheckerWebpackPlugin(),

        new ExtractTextPlugin("bundle.css"),

        new webpack.HashedModuleIdsPlugin(),

        // Ignore all locale files of moment.js
        new webpack.IgnorePlugin(/^\.\/locale$/, /moment$/),

        // Un-comment to run bundle analyzer
        // new BundleAnalyzerPlugin(),
    ],

    stats: {
        warningsFilter: /export .* was not found in/,
    },
});

About this issue

  • Original URL
  • State: closed
  • Created 6 years ago
  • Comments: 21 (11 by maintainers)

Most upvoted comments

I’m glad you’re sorted! There may still be a problem with ts-loader but until a more targeted repro is available I think I’d like to close this.

Thanks for you input on my setup!

Here are replies to your suggestions:

do you want to drop the exclude property? I doubt it’s the problem but I also doubt you need it. outDir - you don’t need this if you’re using webpack. Try dropping it.

The project the repro was derived from is using arcgis-js-api which is stuck deep in the JS past. Among other things, it uses DOJO loader and build process. Suffice to say, it’s a major headache and adding outdir and exclude is a part of the scheme to keep my head from exploding. Also, I run ‘tsc’ as a VS Code task to check the project for errors and I prefer to have the transpiled files dumped somewhere else than the source folders, but I guess I could switch to webpack watch mode or something for that (maybe you have a hint on how to do it?)

noEmitOnError I don’t think you need this and you almost certainly don’t want this given I believe it’s super expensive build time wise. The noEmitOnErrors plugin should be doing this job for you on the webpack side anyway

Good point, will do!

Out of curiosity, why do you import the babel-polyfill given you’re not using Babel? I’d switch to importing core-js (what the Babel polyfill uses under the covers anyway) and strip out Babel entirely.

Will do again!

Why do you import some TypeScript via your webpack build file. I don’t quite follow how that gets built and hence consumed

I understand you ask why I have two typescript files in the webpack entry , right? I ended up doing that because I needed to set the __webpack_public_path__ before any subsequent bundles are requested from the server. I was having problems with webpack loader calling the server before that variable was set by my code, so I split out code setting that variable to a separate module which gets loaded first. Is there a better way to do that? But anyway, I feel that the error I reported might have something to do with the fact that there are two typescript files in entry.

EDIT: I’ve updated the repro project to follow your suggestions