How to select node_modules dist flavor to bundled with webpack
Asked Answered
G

1

10

Problem:

After I upgraded AJV.js to Version 6.4 my vendor bundle includes the "uri-js" ESNEXT version instead the ES5 version what breaks IE11 compatibillity.

Analysis:

I figured that that AJV referes to uri-js with a require('uri-js') call and that uri-js comes in two flavors:

/node_modules/uri-js/dist/:

  • es5
  • esnext

For some reason Webpack (V 4.8) bundles the 'esnext' flavor of uri-js into my vendor-bundle instead using the 'es5'. I couldn't find how/where I have to specify that my preferred build target is.

Here is my webpack.config.js:

const path = require("path");
const webpack = require("webpack");
const ExtractTextPlugin = require("extract-text-webpack-plugin");
const HtmlWebpackPlugin = require("html-webpack-plugin");
const CopyWebpackPlugin = require('copy-webpack-plugin');

module.exports = {
    entry: {
        app: './src/index.tsx'
    },
    output: {
        filename: "js/[name].bundle.js",
        path: __dirname + "/dist"
    },
    devtool: "source-map",
    resolve: {
        extensions: [".ts", ".tsx", ".js", ".jsx", ".json"]
    },
    module: {
        rules: [
            {
                test: /\.tsx?$/,
                loader: "ts-loader"
            },
            {
                test: /\.less$/,
                use: ExtractTextPlugin.extract({
                    use: [{
                        loader: "css-loader",
                        options: {
                            localIdentName: '[local]--[hash:5]',
                            sourceMap: true
                        }

                    }, {
                        loader: "less-loader",
                        options: {
                            sourceMap: true
                        }
                    }],
                    fallback: "style-loader",
                    publicPath: "../"
                }),
                exclude: "/node_modules/"
            },
            {
                test: /\.html$/,
                use: 'raw-loader'
            },
            {
                test: /\.jpe?g$|\.gif$|\.png$/i,
                loader: "file-loader?name=assets/img/[name].[ext]"
            },
            {
                test: /\.woff2?$|\.ttf$|\.eot$|\.svg$/,
                use: "file-loader?name=assets/[name].[ext]"
            }
        ]
    },
    plugins: [
        new ExtractTextPlugin({
            filename: "quino/style/style.css",
            allChunks: true
        }),
        new HtmlWebpackPlugin({
            template: "src/index.html",
            filename: "index.html"
        }),
        new CopyWebpackPlugin([])
    ],
    optimization: {
        splitChunks: {
            cacheGroups: {
                commons: { test: /[\\/]node_modules[\\/]/, name: "vendors", chunks: "all" }
            }
        }
    }
};

package.json:

{
  "name": "MyApp",
  "version": "1.0.0",
  "sideEffects": false,
  "description": "-",
  "private": false,
  "scripts": {
    "build": "webpack --config webpack.config.js --mode production",
    "dev": "webpack-dev-server --config webpack.config.js --host 0.0.0.0 --progress --colors --history-api-fallback --mode development"
  },
  "author": "Me",
  "license": "some",
  "devDependencies": {
   .... stuff ....
  },
  "dependencies": {
    .... stuff ....
    "ajv": "^6.4.0",
    .... more stuff ....
  }
}

I do understand that my own code gets transpiled to ES5 using the TypeScript (V 2.8) compiler. But what about the node_modules? Especially the one that already ship a ES5 version within their dist-folder?

In case it matters here my tsconfig.json:

{
  "compilerOptions": {
    "outDir": "build/dist",
    "module": "esnext",
    "target": "es5",
    "lib": ["es6", "dom"],
    "sourceMap": true,
    "allowJs": true,
    "jsx": "react",
    "moduleResolution": "node",
    "rootDir": "src",
    "forceConsistentCasingInFileNames": true,
    "noImplicitReturns": true,
    "noImplicitThis": true,
    "noImplicitAny": true,
    "strictNullChecks": true,
    "suppressImplicitAnyIndexErrors": true,
    "noUnusedLocals": true,
    "experimentalDecorators": true,
    "emitDecoratorMetadata": true
  },
  "exclude": [
    "dist/**",
    "./*.js",
    "node_modules",
    "build",
    "scripts",
    "acceptance-tests",
    "webpack",
    "jest",
    "src/setupTests.ts"
  ]
}

I also thought about including Babel to downgrade all node_modules to ES5 but that sounds like an overkill to me especially as the modules have included ES5 flavors already.

Questions:

  1. Can I specify that I prefere ES5 version of the dist folder for my node_modules? Maybe in my webpack.config or in package.json?

  2. How does the selection of the right node_modules/.../dist/ folders work?

Goggles answered 16/5, 2018 at 6:57 Comment(6)
Have you looked at github.com/garycourt/uri-js/issues/32 And also from a debugging perspective have you tried to include this package as part of your Typescript compilation?Onega
Why do you think that using babel is a overkill?? It does perfect sense. Especially at situations like this. You dont need to look behind (ES5) anymore. Debuging vendor dependencies for specs? Really?Filose
@AshBelmokadem and @Filose I need fast compiliation turnaround time. If I compile / transpile all the node_modues (>1200) when not needed I will loose a lot of time for this. This will not really work for TDD development where speedy turnaround times are key. In this case the library even ships a already compiled ES5 version. Why this if one can not pick this version? At least not with webpack. Just wonder if there is a mechanism to pick up specific dist-versions of libraries if the libs are shipping them. Make no sense to ship them if not. Right?Goggles
@AshBelmokadem The linked issue sounds like they recommend sticking with an old version (and old version of all the dependencies). Correct?Goggles
@Goggles correct, and I was suggesting to only transpile a single module by including it. You do not need to transpile the entire node_modules folder.Onega
@AshBelmokadem That may be an option. The problem is that it gets kind of tricky as node_modules is not within my TS root directory. I have to change all my config quite a bit or feature bable which don't yet use at all. But yes, maybe I have to do this.Goggles
G
2
  1. Can I specify that I prefere ES5 version of the dist folder for my node_modules? Maybe in my webpack.config or in package.json?

As I understand there is no common way for handling different flavor (eg. ES5, ESNEXT, etc.) of the same NPM package. Each package has its own way of doing things. So there is no general way of choosing things. Instead one have to incorporate stuff into your task-runner (Gulp, Webpack, Grunt, etc) to address problems arise.

  1. How does the selection of the right node_modules/.../dist/ folders work?

A NPM package contains a package.json. Within this file there is a main field which specifies what to include/use in your app or what gets picked by the bundler etc. If no main value exists index.js will be used as the default.

The rest of the selection process is package-specific. This applies also to the folder structure of a package. Some use /dist/.. for different flavors others ship debug and production version in other folders. Highly depends on each package itself what files/versions of files are used.

There is no standardized system like in .net Nuget packages the structure of the lib/... folder.

What I am still not sure about is why ESNEXT version of URL-JS gets picked as the URL-JS points to its ES5 version. Working on this one ;-)

Goggles answered 12/6, 2018 at 9:20 Comment(3)
I have the exact same problem in my code. Have you been able to solve this?Sheree
For Ajv I got a pull-request merged to do the minor update so the working version of the Url packages get pulled. You can also add a dependency in your apps package.json to force a newer version of the Url NPM. Speaking more generally there seems to be no concept in NPM to force a specific platform / flavor. Its all up the each packages authors.Goggles
I just saw, that I am already on [email protected]. However I am still getting the Syntax Error in IE. I also read that uri-js uses a newer version of punycode(2.1.1), which doesn't support IE. Do you have an idea, why I still face the issue with the 4.2.2 version?Sheree

© 2022 - 2025 — McMap. All rights reserved.