【问题标题】:webpack jquery plugin loading its own instance of jquerywebpack jquery 插件加载它自己的 jquery 实例
【发布时间】:2017-02-27 17:21:25
【问题描述】:

我一直在尝试通过 webpack 加载一个 jquery 插件。 这个插件被打包为一个 npm 模块,并且在它的依赖项中只包含 jquery。 我认为 webpack 会加载该 jquery 实例,而不是使用我通过 ProvidePlugin 全局提供的实例。 我尝试了另一个 stackoverflow 帖子 (Managing jQuery plugin dependency in webpack) 中提供的所有解决方案,但他们没有成功;结果总是一样的:“终端()不是一个函数”。 如果我手动修改 node_modules 文件夹中的包,删除 package.json 中的 jquery 依赖项,并且 node_modules 插件文件夹中下载的依赖项 webpack 成功地将插件与 jquery 的全局实例绑定。 我知道,我可以简单地对该包进行分叉并使用私有 npm 存储库,但我想使用官方包。

这是我的 webpack 配置:

var webpack = require('webpack');
var HtmlWebpackPlugin = require('html-webpack-plugin');
var CleanWebpackPlugin = require('clean-webpack-plugin');
var CopyWebpackPlugin = require('copy-webpack-plugin');
var ExtractTextPlugin = require('extract-text-webpack-plugin');
var moment = require('moment');
var path = require('path');
var environment = process.env.APP_ENVIRONMENT || 'dev';

module.exports = {

  entry: {
    'app': './src/main.ts',
    'polyfills': './src/polyfills.ts',
    'vendor': './src/vendor.ts'
  },
  /*devtool: 'source-map',*/
  output: {
    path: './dist',
    filename: '[name].browser.' + moment().format('DDMMYYYYHHmm') + '.js'
  },
  module: {
    loaders: [
      { test: /\.component.ts$/, loader: 'ts!angular2-template' },
      { test: /\.ts$/, exclude: /\.component.ts$/, loader: 'ts' },
      { test: /\.html$/, loader: 'raw-loader' },
      { test: /\.css$/, include: path.resolve('src/app'), loader: 'raw-loader' },
      {
        test: /\.css$/, exclude: path.resolve('src/app'), loader: ExtractTextPlugin.extract('style', 'css', {
          fallbackLoader: "style-loader",
          loader: "css-loader"
        })
      },
      { test: /\.(png|jpe?g|gif|ico)$/, loader: 'file?name=fonts/[name].[ext]' },
      { test: /\.woff(\?v=\d+\.\d+\.\d+)?$/, loader: "url?limit=10000&mimetype=application/font-woff&name=fonts/[name].[ext]" },
      { test: /\.woff2(\?v=\d+\.\d+\.\d+)?$/, loader: "url?limit=10000&mimetype=application/font-woff&name=fonts/[name].[ext]" },
      { test: /\.ttf(\?v=\d+\.\d+\.\d+)?$/, loader: "url?limit=10000&mimetype=application/octet-stream&name=fonts/[name].[ext]" },
      { test: /\.eot(\?v=\d+\.\d+\.\d+)?$/, loader: "file?name=fonts/[name].[ext]" },
      { test: /\.svg(\?v=\d+\.\d+\.\d+)?$/, loader: "url?limit=10000&mimetype=image/svg+xml&name=fonts/[name].[ext]" },
    ]
  },
  resolve: {
    extensions: ['', '.js', '.ts', '.html', '.css']
  },
  plugins: [
    new webpack.optimize.CommonsChunkPlugin({
      name: ['vendor', 'polyfills']
    }),
    new HtmlWebpackPlugin({
      template: './src/index.html'
    }),
    new webpack.DefinePlugin({
      app: {
        environment: JSON.stringify(environment),
        config: JSON.stringify(require('./profile/' + environment + ".profile.js"))
      }
    }),
    new CleanWebpackPlugin(
      ['dist']
    ),
    new CopyWebpackPlugin([
      { from: './src/images', to: 'images' }
    ]),
    new ExtractTextPlugin('[name].browser.css'),
    new webpack.optimize.UglifyJsPlugin({ minimize: true }),
    new webpack.ProvidePlugin({
      $: "jquery",
      jQuery: "jquery",
      "window.jQuery": "jquery"
    })
  ]
};

这里是 jquery.terminal package.json:

{
  "_args": [
    [
      {
        "raw": "jquery.terminal@0.11.11",
        "scope": null,
        "escapedName": "jquery.terminal",
        "name": "jquery.terminal",
        "rawSpec": "0.11.11",
        "spec": "0.11.11",
        "type": "version"
      },
      "/home/giovanni/Projects/Private/site"
    ]
  ],
  "_from": "jquery.terminal@0.11.11",
  "_id": "jquery.terminal@0.11.11",
  "_inCache": true,
  "_installable": true,
  "_location": "/jquery.terminal",
  "_nodeVersion": "4.2.6",
  "_npmOperationalInternal": {
    "host": "packages-16-east.internal.npmjs.com",
    "tmp": "tmp/jquery.terminal-0.11.11.tgz_1475868856610_0.3736777463927865"
  },
  "_npmUser": {
    "name": "jcubic",
    "email": "jcubic@onet.pl"
  },
  "_npmVersion": "3.5.2",
  "_phantomChildren": {},
  "_requested": {
    "raw": "jquery.terminal@0.11.11",
    "scope": null,
    "escapedName": "jquery.terminal",
    "name": "jquery.terminal",
    "rawSpec": "0.11.11",
    "spec": "0.11.11",
    "type": "version"
  },
  "_requiredBy": [
    "#USER",
    "/"
  ],
  "_resolved": "https://registry.npmjs.org/jquery.terminal/-/jquery.terminal-0.11.11.tgz",
  "_shasum": "eaeed2f8f305ac0477d71ef492e7d98d6064d812",
  "_shrinkwrap": null,
  "_spec": "jquery.terminal@0.11.11",
  "_where": "/home/giovanni/Projects/Private/site",
  "author": {
    "name": "Jakub Jankiewicz",
    "email": "jcubic@onet.pl",
    "url": "http://jakub.jankiewi.cz"
  },
  "bugs": {
    "url": "https://github.com/jcubic/jquery.terminal/issues"
  },
  "dependencies": {
    "jquery": "^2.1.4"
  },
  "description": "jQuery Terminal Emulator is a plugin for creating command line interpreters in your applications.",
  "devDependencies": {
    "istanbul": "^0.4.3",
    "jasmine": "^2.4.1",
    "jasmine-node": "^1.14.5",
    "jsdom": "^3.1.2"
  },
  "directories": {},
  "dist": {
    "shasum": "eaeed2f8f305ac0477d71ef492e7d98d6064d812",
    "tarball": "https://registry.npmjs.org/jquery.terminal/-/jquery.terminal-0.11.11.tgz"
  },
  "gitHead": "0f2e55a6501d96aa17d42e4fcc071fab906309d8",
  "homepage": "http://terminal.jcubic.pl",
  "keywords": [
    "terminal",
    "emulator",
    "prompt",
    "console",
    "keyboard",
    "type",
    "rpc",
    "input",
    "ui"
  ],
  "license": "MIT",
  "main": "js/jquery.terminal-0.11.11.js",
  "maintainers": [
    {
      "name": "jcubic",
      "email": "jcubic@onet.pl"
    }
  ],
  "name": "jquery.terminal",
  "optionalDependencies": {},
  "readme": "ERROR: No README data found!",
  "repository": {
    "type": "git",
    "url": "git+https://github.com/jcubic/jquery.terminal.git"
  },
  "scripts": {},
  "version": "0.11.11"
}

【问题讨论】:

    标签: javascript jquery jquery-plugins webpack jquery-terminal


    【解决方案1】:

    对于yarn 包管理器,另一种解决方案是强制使用主应用程序的库依赖项。通过在package.json 中指定resolutions,它可以用来防止下载不同版本的sub-dependencies。除了你的应用程序使用的东西。

    如果您的软件包是公开重新分发,则您应该使用此解决方案。

    问题

    例如,如果您的应用程序依赖于"jquery": "~1.12.0"jquery-plugin,其中包括它自己的dependencies: { "jquery": ">=1.9" }。假设jquery的最新版本是3.4.1,运行yarn install会下载一个类似的目录结构。

    node_modules
        jquery@1.12.4
        jquery-plugin
            node_modules
                 jquery@3.4.1
    
    //app.js
    const $ = require('jquery');
    require('jquery-plugin');
    console.log(typeof $.fn.plugin); //undefined
    

    解决方案

    resolutions 字段添加到您的package.json 文件并定义您的版本覆盖。

    package.json

    强制 ALL 子依赖使用 jQuery ~1.12.0

    {
        "name": "project-name",
         "dependencies": {
             "jquery": "~1.12.0",
             "jquery-plugin": "*"
         },
         "resolutions": {
             "jquery": "~1.12.0"
         }
    }
    

    强制 jquery-plugin 使用 jQuery ~1.12.0

    {
        "name": "project-name",
         "dependencies": {
             "jquery": "~1.12.0",
             "jquery-plugin": "*"
         },
         "resolutions": {
             "jquery-plugin/jquery": "~1.12.0"
         }
    }
    

    然后运行yarn install

    结果删除了重复的 jquery 子依赖项。

    node_modules
        jquery@1.12.4
        jquery-plugin
    
    //app.js
    const $ = require('jquery');
    require('jquery-plugin');
    console.log(typeof $.fn.plugin); //function
    

    【讨论】:

      【解决方案2】:

      我通过稍微修改我的 Webpack 配置解决了我的问题。 正如这里 (Managing jQuery plugin dependency in webpack) 所建议的,我添加了一个 jquery 别名。 在提供的示例中,别名是静态指定的,它对我不起作用。 我切换到一个动态值并解决了问题。

      这里是sn-p:

      alias: {
            'jquery': path.resolve(path.join(__dirname, 'node_modules', 'jquery'))
           },

      【讨论】:

      • 这对我有帮助。我使用 jquery/src/jquery 作为别名,但很少有旧的 jquery 插件在其 package.json 中有依赖项,并且此别名与错误的目录匹配。例如:some-jquery-plugin/node_modules/jquery/src/jquery 当插件将 jQuery 作为依赖项时。使用jquery/src/jquery 作为别名,我的 vendor.js 中有两个不同版本的 jQuery,因为旧的 jQuery 插件在 jQuery 1.0.0 和 yarn/npm 确实下载了 jQuery 3 而我的项目需要旧版本 1.12.4
      • 在我的项目中使用三个 jquery 插件(jquery-asScrollable、jquery-asScrollbar 和 jquery-asHoverScroll)时,我遇到了这个问题,这个答案为我指明了正确的方向。就我而言,静态别名 jquery: "jquery/src/jquery" 解决了我的问题。谢谢!!
      • 非常感谢。我一直在寻找这个指导超过一天。我将第三方 bootstrap 4 主题与一长串供应商依赖项捆绑在一起,它是自己的 gulp-webpack 任务。在注意到不同插件的许多不一致的成功之后——主要集中在 jquery 上——我发现很难确定每个模块是否引用了相同的 jquery 依赖项。这种技术立即对我有用。
      【解决方案3】:

      不熟悉 jquery.terminal,但明确告诉插件如何加载 jQuery 可能会有所帮助。对于类似问题,我不得不为几个插件执行此操作。

          loaders: [{
              test: /jquery.terminal.+\.(js)$/,
              loader: 'imports?jQuery=jquery,$=jquery,this=>window'
          }]
      

      【讨论】:

      • 感谢@Quotidian 的回复,不过我刚刚解决了这个问题!。我即将发布答案。
      猜你喜欢
      • 2017-06-26
      • 2017-10-02
      • 1970-01-01
      • 1970-01-01
      • 2015-07-19
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多