如何选择 node_modules dist 风格与 webpack 捆绑

Posted

技术标签:

【中文标题】如何选择 node_modules dist 风格与 webpack 捆绑【英文标题】:How to select node_modules dist flavor to bundled with webpack 【发布时间】:2018-10-26 02:49:09 【问题描述】:

问题:

在我将 AJV.js 升级到版本 6.4 后,我的供应商捆绑包包含“uri-js”ESNEXT 版本,而不是破坏 IE11 兼容性的 ES5 版本。

分析:

我认为 AJV 通过 require('uri-js') 调用引用 uri-js,并且 uri-js 有两种风格:

/node_modules/uri-js/dist/:

es5 esnext

出于某种原因,Webpack (V 4.8) 将 uri-js 的“esnext”风格捆绑到我的供应商捆绑包中,而不是使用“es5”。我找不到我必须如何/在哪里指定我的首选构建目标。

这是我的 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 ....
  

我知道我自己的代码使用 TypeScript (V 2.8) 编译器被转译为 ES5。但是 node_modules 呢?尤其是已经在他们的 dist 文件夹中发布了 ES5 版本的那个?

如果这里很重要,我的 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"
  ]

我还考虑包含 Babel 以将所有 node_modules 降级到 ES5,但这对我来说听起来有点矫枉过正,特别是因为模块已经包含 ES5 风格。

问题:

    我可以为我的node_modules 指定我更喜欢dist 文件夹的ES5 版本吗?也许在我的 webpack.config 或 package.json 中?

    如何选择正确的node_modules/.../dist/ 文件夹?

【问题讨论】:

你看过github.com/garycourt/uri-js/issues/32 并且从调试的角度来看,你是否尝试过将这个包作为你的 Typescript 编译的一部分? 为什么你认为使用 babel 是大材小用?它确实很有意义。尤其是在这样的情况下。您不再需要向后看(ES5)。调试规范的供应商依赖项?真的吗? @AshBelmokadem 和 @bigless 我需要快速的编译周转时间。如果我在不需要时编译/转换所有node_modues (>1200),我会为此浪费很多时间。这对于快速周转时间是关键的 TDD 开发来说并不适用。在这种情况下,库甚至发布了一个已经编译好的 ES5 版本。如果一个人不能选择这个版本,为什么会这样?至少不会使用 webpack。只是想知道如果库正在运送它们,是否有一种机制来获取库的特定 dist 版本。如果没有,运送它们是没有意义的。对吗? @AshBelmokadem 链接的问题听起来像是他们建议坚持使用旧版本(以及所有依赖项的旧版本)。对吗? @Marc 正确,我建议只通过包含一个模块来转换它。您不需要编译整个 node_modules 文件夹。 【参考方案1】:
    我可以为我的 node_modules 指定我更喜欢 ES5 版本的 dist 文件夹吗?也许在我的 webpack.config 或 package.json 中?

据我所知,处理同一个 NPM 包的不同风格(例如 ES5、ESNEXT 等)没有通用方法。每个包都有自己的做事方式。所以没有一般​​的选择事物的方法。相反,必须将一些东西合并到您的任务运行程序(Gulp、Webpack、Grunt 等)中以解决出现的问题。

    如何选择正确的 node_modules/.../dist/ 文件夹?

一个 NPM 包包含一个 package.json。在这个文件中有一个main 字段,它指定在您的应用程序中包含/使用的内容或捆绑程序选择的内容等。如果不存在main 值,则index.js 将用作默认值。

选择过程的其余部分是特定于包的。这也适用于包的文件夹结构。有些人使用/dist/.. 来表示不同的风格,其他人则在其他文件夹中提供调试和生产版本。高度依赖于每个包本身使用什么文件/文件版本。

没有像 .net Nuget 中那样的标准化系统封装lib/... 文件夹的结构。

我仍然不确定的是,为什么在 URL-JS 指向其 ES5 版本时选择了 ESNEXT 版本的 URL-JS。处理这个;-)

【讨论】:

我的代码中有完全相同的问题。你能解决这个问题吗? 对于 Ajv,我合并了一个拉取请求以进行次要更新,以便拉取 Url 包的工作版本。您还可以在您的应用程序 package.json 中添加一个依赖项以强制更新版本的 Url NPM。更一般地说,NPM 中似乎没有强制特定平台/风格的概念。每个包的作者都是如此。 我刚刚看到,我已经在 uri-js@4.2.2 上。但是我仍然在 IE 中收到语法错误。我还读到 uri-js 使用了不支持 IE 的更新版本的 punycode(2.1.1)。你有什么想法,为什么我仍然面临 4.2.2 版本的问题?

以上是关于如何选择 node_modules dist 风格与 webpack 捆绑的主要内容,如果未能解决你的问题,请参考以下文章

使用 Webpack 解析从 node_modules 到 Dist 文件夹的相对路径

Vue 3:模块 '"../../node_modules/vue/dist/vue"' 没有导出成员

Gatsby - 错误:找不到模块 '..\node_modules\gatsby\dist\utils\babel-loader.js'

引导反应./node_modules/bootstrap/dist/js/bootstrap.min.js 找不到模块:无法解析'jquery'

ENOENT: node_modules\jquery\dist\jquery.min.js'没有这样的文件或目录

模块构建失败(来自 ./node_modules/sass-loader/dist/cjs.js)