-1

We have a typescript react 'main' project. In the package.json is a dependency on another internal library that we use. The 'main' project builds fine when both projects targeted es5, but changing to es2017 throws the following error:

You may need an appropriate loader to handle this file type, currently no loaders are configured to process this file.

It throws this error for all the files that declare enums in the dependent project.

This is the tsconfig.json file for the main project:

{
  "compilerOptions": {
    "resolveJsonModule": true,
    "noImplicitAny": false,
    "module": "commonjs",
    "noEmitOnError": true,
    "removeComments": false,
    "sourceMap": true,
    "target": "es2017",
    "jsx": "react",
    "esModuleInterop": true,
    "allowSyntheticDefaultImports": true,
    "experimentalDecorators": true,
    "downlevelIteration": true,
    "types": ["node", "jest"],
    "baseUrl": "./src"
  },
  "exclude": ["node_modules"],
  "includes": ["./src"]
}

And the webpack.config.js:

/* eslint no-use-before-define: 0 */
const path = require('path');
const webpack = require('webpack');

// plugins
const CopyPlugin = require('copy-webpack-plugin');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const TerserPlugin = require('terser-webpack-plugin');
const ForkTsCheckerWebpackPlugin = require('fork-ts-checker-webpack-plugin');

const isProduction = process.env.NODE_ENV === 'production';

//entry --> output
module.exports = {
  context: __dirname,
  devtool: isProduction ? 'source-map' : 'eval-source-map',
  entry: {
    app: ['./src/index.tsx'],
  },
  output: {
    path: path.join(__dirname, 'site'),
    filename: '[name].[contenthash].js',
    publicPath: '/',
  },
  devServer: {
    inline: true,
    hot: true,
    historyApiFallback: true,
    disableHostCheck: true,
  },
  resolve: {
    extensions: ['.ts', '.js', '.jsx', '.tsx', '.pdf'],
    alias: {
      api: path.resolve('./src/api'),
      assets: path.resolve('./src/assets'),
      components: path.resolve('./src/components'),
      context: path.resolve('./src/context'),
      hooks: path.resolve('./src/hooks'),
      models: path.resolve('./src/models'),
    },
    fallback: {
      path: require.resolve('path-browserify'),
      util: require.resolve('util'),
    },
  },
  module: {
    rules: [
      {
        test: /\.(js|jsx|ts|tsx)$/,
        exclude: isProduction ? [] : /(node_modules)/,
        use: [
          {
            loader: 'babel-loader',
            options: {
              cacheDirectory: true,
            },
          },
        ],
      },
      {
        test: /\.(pdf)$/,
        exclude: /(node_modules)/,
        use: [
          {
            loader: 'file-loader',
            options: {
              name: '[name].[ext]',
            },
          },
        ],
      },
    ],
  },
  optimization: {
    usedExports: isProduction ? true : false,
    removeAvailableModules: isProduction ? true : false,
    minimize: isProduction ? true : false,
    minimizer: isProduction ? [new TerserPlugin()] : [],
    splitChunks: {
      chunks: 'all',
    },
  },
  plugins: [
    new ForkTsCheckerWebpackPlugin({
      typescript: {
        diagnosticOptions: {
          semantic: true,
          syntactic: true,
        },
      },
    }),
    new webpack.ProvidePlugin({
      process: 'process/browser',
    }),
    new webpack.DefinePlugin({
      'process.env.NODE_ENV': JSON.stringify(
        process.env.NODE_ENV || 'development',
      ),
      'process.env.SENTRY_DSN': `"https://67422e5eff614bc2890330a8825d5c58@o348527.ingest.sentry.io/2686852"`,
      'process.env.APP_VERSION': JSON.stringify(
        process.env.npm_package_version,
      ),
    }),
    new HtmlWebpackPlugin({
      template: 'htmlTemplates/index.wm.template',
      inject: 'body',
      title: 'TIPPEL',
    }),
    new CopyPlugin({
      patterns: [
        {
          from: 'public/images',
          to: 'images',
        },
      ],
      options: {
        concurrency: 100,
      },
    }),
  ],
};

This is the babel.config.json:

{
  "sourceType": "unambiguous",
  "presets": [
    [
      "@babel/preset-env",
      {
        "useBuiltIns": "entry",
        "corejs": 3
      }
    ],
    "@babel/preset-typescript",
    "@babel/preset-react"
  ],
  "plugins": [
    [
      "@babel/plugin-transform-runtime",
      {
        "regenerator": true
      }
    ],
    "@babel/plugin-proposal-class-properties",
    ["@babel/plugin-proposal-object-rest-spread", { "useBuiltIns": true }],
    ["@babel/plugin-transform-destructuring", { "useBuiltIns": true }],
    ["@babel/plugin-transform-object-assign", { "useBuiltIns": true }],
    ["@babel/plugin-transform-arrow-functions", { "useBuiltIns": true }]
  ]
}

From all I've read, nothing special is required to target es2017, so I am wondering what the solution is for this.

IMPORTANT UPDATE

If I change the package json to point to the local copy of the dependent repo (called 'models') then everything compiles.

eg this works:

in package.json: “@tplp/models”: “../models”

but this throws the loader build errors:

in package.json: “@tplp/models”:“2.6.3"

FOR REFERENCE

The same issue occurs with create-react-app if you try to use an npm package that has exports enums, you can read about it here.

For those interested, there are non-npm solutions to sharing typescript code between projects, such as this and this

2nd UPDATE The bable.config.json file has:

"@babel/preset-react"

which causes babel to "remove typescript types". Ref here. Not too sure exactly what they mean by that.

However removing that line (ie removing preset-react) means the build errors for the enums goes away...but of course now none of the JSX can compile.

rmcsharry
  • 5,363
  • 6
  • 65
  • 108
  • 1
    Please reduce this down to an [MRE](https://stackoverflow.com/help/minimal-reproducible-example). i.e. simplify the project and to the bare minimum to reproduce the error. Include one source with Enums and one without and show that it only fails on the source with Enums. – Inigo Jul 07 '21 at 15:17

1 Answers1

0

2 thing led me to the solution. First of all:

The bable.config.json file has:

"@babel/preset-react"

which causes babel to "remove typescript types". Ref here. Removing it gets rid of the errors, since obviously all types are removed (but obviously babel cannot then process JSX).

Thus I realised that the enum files are ambient, and babel-loader (specifically preset-react) doesn't know how to process them (unlike tsc).

That led me to to this SO question, and I realized I had to specifically tell babel-loader where to find the enum files, and so added this to my package.json:

  {
    test: /\.(ts|tsx)$/,
    include: path.resolve('./node_modules/@tplp/models/src/enumerations'),
    use: [
      {
        loader: 'babel-loader',
        options: {
          cacheDirectory: true,
        },
      },
    ]
  },
rmcsharry
  • 5,363
  • 6
  • 65
  • 108