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 librerías como jQuery y React. ¿Qué hago para usar plugins que tienen jQuery como sus dependencias y quiero tenerlos también en vendors.js? ¿Y si esos plugins tienen múltiples dependencias?
Actualmente estoy intentando utilizar este plugin de jQuery - https://github.com/mbklein/jquery-elastic. La documentación de Webpack menciona providePlugin e imports-loader. He utilizado providePlugin, pero el objeto jQuery sigue sin estar 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, sigue arrojando un error en la consola del navegador:
Uncaught ReferenceError: jQuery is not defined
Del mismo modo, cuando utilizo el cargador de importaciones, arroja un error,
require no está definido'
en esta línea:
var jQuery = require("jquery")
Sin embargo, podría usar el mismo plugin cuando no lo añado 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 incluye junto con mi código JavaScript en bundle.js, y quiero que todos mis plugins jQuery estén en el paquete vendors.js. Entonces, ¿cómo puedo hacer para lograr esto?
Usted ha mezclado diferentes enfoques sobre cómo incluir los módulos de proveedores heredados. Así es como yo lo abordaría:
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 poner un alias a la versión src
porque de esta manera webpack es capaz de optimizar mejor las dependencias (por ejemplo, cuando se utiliza 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 bien.
ProvidePlugin
para inyectar globales implícitosLa mayoría de los módulos heredados dependen de la presencia de globals específicos, como los plugins de jQuery hacen con $
o jQuery
. En este caso puedes configurar webpack para que añada var $ = require("jquery")
cada vez que encuentre el identificador global $
.
var webpack = require("webpack");
...
plugins: [
new webpack.ProvidePlugin({
$: "jquery",
jQuery: "jquery"
})
]
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
es igual a module.exports
. En este caso puedes anular this
con el imports-loader.
Ejecuta 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 utilizar 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.
Hay módulos que soportan diferentes estilos de módulos, como AMD, CommonJS y legacy. Sin embargo, la mayoría de las veces primero comprueban la existencia de define
y luego utilizan algún código peculiar para exportar las 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"
}
]
}
Si no te importan las variables globales y sólo quieres que los scripts heredados funcionen, también puedes usar el script-loader. Este ejecuta el módulo en un contexto global, igual que si los hubieras incluido a través de la etiqueta <script>
.
noParse
para incluir discos grandesCuando no hay una versión AMD/CommonJS del módulo y quieres incluir el dist
, puedes marcar este módulo como noParse
. Entonces webpack simplemente incluirá el módulo sin analizarlo, lo que puede utilizarse 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$/
]
}
Para el acceso global a jquery existen varias opciones. En mi proyecto webpack más reciente, quería un acceso global a jquery, así que añadí lo siguiente a las declaraciones de mis plugins:
plugins: [
new webpack.ProvidePlugin({
$: "jquery",
jQuery: "jquery"
})
]
Esto 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 es necesario haber instalado jquery a través de npm:
$ npm i jquery --save
Para un ejemplo de trabajo de este enfoque por favor siéntase libre de fork mi aplicación en github
No sé si entiendo muy bien lo que tratas de hacer, pero tuve que usar plugins 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.$ = $;
Luego solo tengo que requerir donde quiera el jqueryplugin.min.js
y window.$
se extiende con el plugin como se esperaba.