Administrar la dependencia del complemento jQuery en el paquete web

Resuelto booleanhunter asked hace 9 años • 12 respuestas

Estoy usando Webpack en mi aplicación, en la que creo dos puntos de entrada: paquete.js para todos mis archivos/códigos JavaScript y proveedores.js para todas las bibliotecas como jQuery y React. ¿Qué debo hacer para utilizar complementos que tienen jQuery como dependencias y quiero tenerlos también en proveedores.js? ¿Qué pasa si esos complementos tienen múltiples dependencias?

Actualmente estoy intentando utilizar este complemento jQuery aquí: https://github.com/mbklein/jquery-elastic . La documentación de Webpack menciona providePlugin e imports-loader. Utilicé providePlugin, pero el objeto jQuery aún 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 arroja un error en la consola del navegador:

Error de referencia no detectado: jQuery no está definido

De manera similar, cuando uso el cargador de importaciones, arroja un error,

requerir 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 proveedores.js y en su lugar lo necesito de la forma 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 está incluido junto con mi código JavaScript en bundle.js, y quiero que todos mis complementos de jQuery estén en el paquete sellers.js. Entonces, ¿cómo hago para lograr esto?

booleanhunter avatar Mar 11 '15 00:03 booleanhunter
Aceptado

Ha combinado diferentes enfoques sobre cómo incluir módulos de proveedores heredados. Así es como lo abordaría:

1. Prefiera CommonJS/AMD no minificado adist

La mayoría de los módulos vinculan la distversión en el maincampo de su package.json. Si bien esto es útil para la mayoría de los desarrolladores, para webpack es mejor asignar un alias a la srcversión porque de esta manera webpack puede optimizar mejor las dependencias (por ejemplo, cuando se usa DedupePlugin).

// webpack.config.js

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

Sin embargo, en la mayoría de los casos la distversión también funciona bien.


2. Utilice ProvidePluginpara inyectar globales implícitos

La mayoría de los módulos heredados dependen de la presencia de globales específicos, como lo hacen los complementos de jQuery en $o jQuery. En este escenario, puede configurar el paquete web para anteponerlo var $ = require("jquery")cada vez que encuentre el $identificador global.

var webpack = require("webpack");

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

3. Utilice el cargador de importaciones para configurarthis

Algunos módulos heredados dependen de thisser el windowobjeto. Esto se convierte en un problema cuando el módulo se ejecuta en un contexto CommonJS donde thises igual a module.exports. En este caso, puede anular thiscon el cargador de importaciones .

Corre npm i imports-loader --save-devy luego

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

El cargador de importaciones también se puede utilizar para inyectar manualmente variables de todo tipo. Pero la mayoría de las veces ProvidePlugines más útil cuando se trata de globales implícitos.


4. Utilice el cargador de importaciones para desactivar AMD

Hay módulos que admiten diferentes estilos de módulos, como AMD, CommonJS y Legacy. Sin embargo, la mayoría de las veces primero verifican definey luego usan algún código peculiar para exportar propiedades. En estos casos, podría ser útil forzar la ruta CommonJS configurando define = false.

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

5. Utilice el cargador de scripts (que ya no se mantiene) para importar scripts globalmente

Si no le importan las variables globales y solo desea que funcionen los scripts heredados, también puede utilizar el cargador de scripts. Ejecuta el módulo en un contexto global, como si los hubieras incluido a través de la <script>etiqueta.


6. Úselo noParsepara incluir distribuciones grandes

Cuando no hay una versión AMD/CommonJS del módulo y desea incluir dist, puede marcar este módulo como noParse. Luego, el paquete web simplemente incluirá el módulo sin analizarlo, lo que puede usarse para mejorar el tiempo de compilación. Esto significa que cualquier función que requiera AST , como ProvidePlugin, no funcionará.

module: {
    noParse: [
        /[\/\\]node_modules[\/\\]angular[\/\\]angular\.js$/
    ]
}
Johannes Ewald avatar Mar 11 '2015 14:03 Johannes Ewald

Para el acceso global a jquery existen varias opciones. En mi proyecto de paquete web más reciente, quería acceso global a jquery, así que agregué lo siguiente a mis declaraciones de complementos:

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

Esto significa que se puede acceder a jquery desde el código fuente de JavaScript a través de referencias globales $ y jQuery.

Por supuesto, también debes tener instalado jquery a través de npm:

$ npm i jquery --save

Para ver un ejemplo práctico de este enfoque, no dude en bifurcar mi aplicación en github.

arcseldon avatar Dec 18 '2015 11:12 arcseldon

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

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

Solo tengo que solicitarlo donde quiera jqueryplugin.min.jsy window.$se extiende con el complemento como se esperaba.

sanfilippopablo avatar May 19 '2015 17:05 sanfilippopablo

Conseguí que todo funcionara bien al exponer $y jQuerycomo variables globales con Webpack 3.8.1 y siguientes.

Instale jQuery como una dependencia del proyecto. Puede omitir @3.2.1instalar la última versión o especificar otra versión.

npm install --save jquery@3.2.1

Instálelo expose-loadercomo una dependencia de desarrollo si aún no está instalado.

npm install expose-loader --save-dev

Configure Webpack para cargar y exponer jQuery por 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'
    })
  ]
}
HarlemSquirrel avatar Oct 25 '2017 16:10 HarlemSquirrel