Administrar la dependencia del complemento jQuery en el paquete web
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?
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 dist
versión en el main
campo 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 src
versió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 dist
versión también funciona bien.
2. Utilice ProvidePlugin
para 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 this
ser el window
objeto. 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, puede anular this
con el cargador de importaciones .
Corre npm i imports-loader --save-dev
y 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 ProvidePlugin
es 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 define
y 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 noParse
para 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$/
]
}
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.
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.js
y window.$
se extiende con el complemento como se esperaba.
Conseguí que todo funcionara bien al exponer $
y jQuery
como variables globales con Webpack 3.8.1 y siguientes.
Instale jQuery como una dependencia del proyecto. Puede omitir @3.2.1
instalar la última versión o especificar otra versión.
npm install --save jquery@3.2.1
Instálelo expose-loader
como 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'
})
]
}