Búsqueda de sitios web

javascript - Gestionando la dependencia de un plugin de jQuery en webpack


Estoy usando Webpack en mi aplicación, en la que creo dos puntos de entrada: bundle.js para todos mis archivos/códigos JavaScript, y vendors.js para todas las bibliotecas como jQuery y React. ¿Qué hago para usar plugins que tienen jQuery como dependencia y quiero que también estén en vendors.js? ¿Qué pasa si esos plugins tienen múltiples dependencias?

Actualmente estoy tratando de usar este plugin de jQuery aquí - https://github.com/mbklein/jquery-elastic. La documentación de Webpack menciona providePlugin e imports-loader. Usé providePlugin, pero aún así el objeto jQuery no está disponible. Así es como se ve mi webpack.config.js-

var webpack = require('webpack');
var bower_dir = __dirname + '/bower_components';
var node_dir = __dirname + '/node_modules';
var lib_dir = __dirname + '/public/js/libs';

var config = {
    addVendor: function (name, path) {
        this.resolve.alias[name] = path;
        this.module.noParse.push(new RegExp(path));
    },
    plugins: [
        new webpack.ProvidePlugin({
            $: "jquery",
            jquery: "jQuery",
            "window.jQuery": "jquery"
        }),
        new webpack.optimize.CommonsChunkPlugin('vendors', 'vendors.js', Infinity)
    ],
    entry: {
        app: ['./public/js/main.js'],
        vendors: ['react','jquery']
    },
    resolve: {
        alias: {
            'jquery': node_dir + '/jquery/dist/jquery.js',
            'jquery.elastic': lib_dir + '/jquery.elastic.source.js'
        }
    },
    output: {
        path: './public/js',
        filename: 'bundle.js'
    },
    module: {
        loaders: [
            { test: /\.js$/, loader: 'jsx-loader' },
            { test: /\.jquery.elastic.js$/, loader: 'imports-loader' }
        ]
    }
};
config.addVendor('react', bower_dir + '/react/react.min.js');
config.addVendor('jquery', node_dir + '/jquery/dist/jquery.js');
config.addVendor('jquery.elastic', lib_dir +'/jquery.elastic.source.js');

module.exports = config;

Pero a pesar de esto, todavía lanza un error en la consola del navegador:

Error de referencia no capturado: jQuery no está definido

De manera similar, cuando uso el imports-loader, arroja un error,

'require' no está definido

en esta línea:

var jQuery = require("jquery")

Sin embargo, podría usar el mismo complemento cuando no lo agrego a mi archivo vendors.js y, en su lugar, lo requiero de la manera normal de AMD, como incluyo mis otros archivos de código JavaScript, como-

define(
[
    'jquery',
    'react',
    '../../common-functions',
    '../../libs/jquery.elastic.source'
],function($,React,commonFunctions){
    $("#myInput").elastic() //It works

});

Pero esto no es lo que quiero hacer, ya que esto significaría que jquery.elastic.source.js se incluya junto con mi código JavaScript en bundle.js, y quiero que todos mis complementos de jQuery estén en el paquete vendors.js. Entonces, ¿cómo puedo lograr esto?

Respuesta #1

Has mezclado diferentes enfoques sobre cómo incluir módulos de proveedores antiguos. Así es como lo abordaría:

1. Prefiera CommonJS/AMD sin minificar sobre dist

La mayoría de los módulos enlazan la versión dist en el campo main de su package.json. Aunque esto es útil para la mayoría de los desarrolladores, para webpack es mejor hacer un alias de la versión src porque de esta manera webpack puede optimizar mejor las dependencias (por ejemplo, al usar el DedupePlugin).

// webpack.config.js

module.exports = {
    ...
    resolve: {
        alias: {
            jquery: "jquery/src/jquery"
        }
    }
};

Sin embargo, en la mayoría de los casos la versión dist también funciona perfectamente.


2. Usa el ProvidePlugin para inyectar variables globales implícitas

La mayoría de los módulos heredados dependen de la presencia de globales específicos, como los plugins de jQuery dependen de $ o jQuery. En este escenario, puedes configurar webpack para anteponer var $=require("jquery") cada vez que encuentre el identificador global $.

var webpack = require("webpack");

    ...
    
    plugins: [
        new webpack.ProvidePlugin({
            $: "jquery",
            jQuery: "jquery"
        })
    ]

3. Usa el imports-loader para configurar this

Algunos módulos heredados dependen de que this sea el objeto window. Esto se convierte en un problema cuando el módulo se ejecuta en un contexto CommonJS donde this equivale a module.exports. En este caso, puedes sobrescribir this con el imports-loader.

Ejecute npm i imports-loader --save-dev y luego

module: {
    loaders: [
        {
            test: /[\/\\]node_modules[\/\\]some-module[\/\\]index\.js$/,
            loader: "imports-loader?this=>window"
        }
    ]
}

El imports-loader también se puede usar para inyectar manualmente variables de todo tipo. Pero la mayoría de las veces, el ProvidePlugin es más útil cuando se trata de globales implícitos.


4. Usa el imports-loader para desactivar AMD

Hay módulos que soportan diferentes estilos de módulo, como AMD, CommonJS y legacy. Sin embargo, la mayoría de las veces primero verifican define y luego usan un código peculiar para exportar propiedades. En estos casos, podría ayudar forzar la ruta de CommonJS estableciendo define=false.

module: {
    loaders: [
        {
            test: /[\/\\]node_modules[\/\\]some-module[\/\\]index\.js$/,
            loader: "imports-loader?define=>false"
        }
    ]
}

5. Usa el script-loader (ya no mantenido) para importar scripts globalmente

Si no te importan las variables globales y solo quieres que los scripts heredados funcionen, también puedes usar el cargador de scripts. Ejecuta el módulo en un contexto global, tal como si los hubieras incluido mediante la etiqueta <script>.


6. Usa noParse para incluir distribuciones grandes

Cuando no hay una versión AMD/CommonJS del módulo y quieres incluir el dist, puedes marcar este módulo como noParse. Entonces webpack solo incluirá el módulo sin analizarlo, lo que se puede usar para mejorar el tiempo de compilación. Esto significa que cualquier característica que requiera el AST, como el ProvidePlugin, no funcionará.

module: {
    noParse: [
        /[\/\\]node_modules[\/\\]angular[\/\\]angular\.js$/
    ]
}

Respuesta #2

Para el acceso global a jQuery existen varias opciones. En mi proyecto más reciente con webpack, quería acceso global a jQuery, así que añadí lo siguiente a mis declaraciones de plugins:

 plugins: [
    new webpack.ProvidePlugin({
      $: "jquery",
      jQuery: "jquery"
    })
  ]

Esto entonces significa que jQuery es accesible desde el código fuente de JavaScript a través de las referencias globales $ y jQuery.

Por supuesto, también necesitas haber instalado jquery mediante npm:

npm i jquery --save

Para un ejemplo funcional de este enfoque, siéntete libre de bifurcar mi aplicación en GitHub

Respuesta #3

No sé si entiendo muy bien lo que estás tratando de hacer, pero tuve que usar complementos de jQuery que requerían que jQuery estuviera en el contexto global (window) y puse lo siguiente en mi entry.js:

var $ = require('jquery');
window.jQuery = $;
window.$ = $;

Entonces solo tengo que requerir donde quiera el jqueryplugin.min.js y window.$ se extiende con el plugin como se esperaba.

Respuesta #4

Hice que las cosas funcionaran bien mientras exponía $ y jQuery como variables globales con Webpack 3.8.1 y lo siguiente.

Instala jQuery como una dependencia del proyecto. Puedes omitir @3.2.1 para instalar la versión más reciente o especificar otra versión.

npm install --save [email 

Instala expose-loader como una dependencia de desarrollo si aún no está instalado.

npm install expose-loader --save-dev

Configura Webpack para cargar y exponer jQuery para nosotros.

// webpack.config.js
const webpack = require('webpack')

module.exports = {
  entry: [
    // entry bits
  ],
  output: {
    // output bits
  },
  module: {
    rules: [
      // any other rules
      {
        // Exposes jQuery for use outside Webpack build
        test: require.resolve('jquery'),
        use: [{
          loader: 'expose-loader',
          options: 'jQuery'
        },{
          loader: 'expose-loader',
          options: '$'
        }]
      }
    ]
  },
  plugins: [
    // Provides jQuery for other JS bundled with Webpack
    new webpack.ProvidePlugin({
      $: 'jquery',
      jQuery: 'jquery'
    })
  ]
}

Respuesta #5

En tu archivo webpack.config.js añade lo siguiente:

 var webpack = require("webpack");
 plugins: [
    new webpack.ProvidePlugin({
        $: "jquery",
        jQuery: "jquery"
    })
 ],

Instalar jQuery usando npm:

npm i jquery --save

En el archivo app.js, agrega las siguientes líneas:

import $ from 'jquery';
window.jQuery = $;
window.$ = $;

Esto funcionó para mí. :)

Respuesta #6

Agrega esto a tu arreglo de plugins en webpack.config.js

new webpack.ProvidePlugin({
    'window.jQuery': 'jquery',
    'window.$': 'jquery',
})

luego requiere jquery normalmente

require('jquery');

Si el dolor persiste al obtener otros scripts para verlo, intenta colocarlo explícitamente en el contexto global a través de (en el js de entrada)

window.$ = jQuery;

Respuesta #7

Probé algunas de las respuestas proporcionadas, pero ninguna parecía funcionar. Entonces intenté esto:

new webpack.ProvidePlugin({
    'window.jQuery'    : 'jquery',
    'window.$'         : 'jquery',
    'jQuery'           : 'jquery',
    '$'                : 'jquery'
});

Parece funcionar sin importar qué versión esté usando

Artículos relacionados