javascript - Paquete web con dos partes comunes: una exportada, una local
webpack (2)
En lo que respecta a su solicitud para poder usar el trozo de proveedor creado en una compilación de paquetes web con paquetes de otra compilación, la única forma que encontré para hacerlo es a través de una combinación de expose-loader y externals
.
En mi caso, utilicé con éxito esto para agrupar jQuery (y Bootstrap) en un "common.js" en una compilación, y luego usar esa jQuery en módulos que pertenecen a otra compilación, de la siguiente manera:
1. Exponer jQuery de construir un trozo
module: {
loaders: [
{
// export jQuery globals for other modules to use as externals
test: require.resolve(''jquery''),
loader: ''expose?$!expose?jQuery''
}
]
}
2. Consumir jQuery en módulos build B
externals: {
''jquery'': ''jQuery''
}
Por supuesto, el inconveniente de esto es que está puenteando entre los dos conjuntos de paquetes mediante el uso de variables globales gestionadas manualmente, que probablemente comenzó a usar webpack para evitar :-)
Sin embargo, no conozco ninguna otra forma en este momento, dado que cada compilación de un paquete web crea su propio espacio de nombres de ID "privadas" internamente a los módulos de referencia, sin garantía de estabilidad o exclusividad global.
Me gustaría usar Webpack en una aplicación de múltiples páginas de tal manera que algunas dependencias predeterminadas se agrupen en una porción de "proveedor" y el resto de las dependencias se incluya en una porción de "bienes comunes".
Por ejemplo, suponiendo dos puntos de entrada (que representan efectivamente una página diferente cada una), pageA.js
y pageB.js
contienen este código (en EC6, procesado a través de Babel), seguido de su propio código:
import $ from ''jquery'';
require(''bootstrap/dist/css/bootstrap.css'');
import angular from ''angular'';
import uitree from ''angular-ui-tree'';
Me gustaría que jQuery y Bootstrap se incluyeran en una porción de "proveedor", y el resto (lo que sea) se incluya en una porción de "bienes comunes".
Los objetivos son:
- Me gustaría poder tener otra compilación separada que pudiera confiar en la misma porción de proveedor, sin que sea necesario volver a incluir las bibliotecas de proveedores (declararía explícitamente ese conjunto de bibliotecas de proveedores, para que esté disponible para cualquier sub-construcción que lo necesita).
- También me gustaría no tener que volver a procesar la porción del proveedor cada vez que hago un cambio en el script de una página.
Aquí está la configuración que he probado:
module.exports = {
entry : {
"vendor" : [ "jquery", "bootstrap" ],
"pageA" : "./src/pageA.js",
"pageB" : "./src/pageB.js"
},
output : {
path : path.join(__dirname, "./dest"),
filename : "[name].chunk.js"
},
module : {
loaders : [ {
test : /bootstrap//js///,
loader : ''imports?jQuery=jquery''
},
/* ... Some modules for angular and CSS processing ... */
{
test : //.js?$/,
include : [ path.resolve(__dirname, "./src") ],
loader : ''babel'',
query : {
presets : [ ''es2015'' ]
}
}
/* ... Some other settings for the fonts ... */ ]
},
plugins : [
new webpack.ProvidePlugin({
$ : "jquery",
jQuery : "jquery"
}),
new webpack.optimize.UglifyJsPlugin({
sourceMap : false,
mangle : false,
compress : false
}),
new CommonsChunkPlugin({
name : "vendor",
minChunks : Infinity
}),
new CommonsChunkPlugin({
name : "commons",
minChunks : 2
})
]
};
Con la configuración anterior, obtengo jQuery y Bootstrap en vendor.chunk.js
, según sea necesario, pero el archivo commons.chunk.js
está casi vacío, todo el resto de lo que es comúnmente usado por pageA.js
y pageB.js
se coloca en pageA.chunk.js
y pageB.chunk.js
(efectivamente duplicando ese código).
Si cambio el orden de los dos últimos complementos, commons.chunk.js
ahora contiene casi todo (a menos que sea realmente específico para pageA.js
y pageB.js
), y vendor.chunk.js
está casi vacío:
plugins : [
// ...,
new CommonsChunkPlugin({
name : "commons",
minChunks : 2
}),
new CommonsChunkPlugin({
name : "vendor",
minChunks : Infinity
})
]
¿Hay alguna forma de agrupar una lista predefinida de bibliotecas (por ejemplo, [ "jquery", "jquery-ui", "bootstrap" ]
en un fragmento en particular (de tal manera que pueda ser utilizada por scripts completamente independientes) y ¿También tiene otra porción común para cualquier otra cosa que se use comúnmente entre los puntos de entrada?
El objetivo de todo esto sería poder construir un fragmento de código completamente separado para otra página más adelante y decirle que no es necesario volver a agrupar esas bibliotecas predefinidas.
Aquí hay un diagrama que representa lo que estoy tratando de lograr:
Luego usaría los scripts generados de la siguiente manera:
<script src="vendor.js"></script>
<script src="common.js"></script>
<script src="pageA.chunk.js"></script>
Y en la página C (construida de forma completamente independiente de las páginas A y B):
<script src="vendor.js"></script>
<script src="common2.js"></script>
<script src="pageC.chunk.js"></script>
(Estoy usando Webpack 1.12.14.)
He intentado la solución sugerida en la única respuesta hasta ahora . Si bien esto hace posible separar la parte del proveedor de la parte de los comunes, los fragmentos del proveedor (con la misma definición) hechos de dos versiones separadas generalmente no pueden intercambiarse entre sí. Esto no hace posible utilizar solo uno de esos fragmentos de proveedores en dos versiones (aunque son prácticamente iguales).
Estaba trabajando en algo similar. Observé el comportamiento que deseas al tener esta configuración:
const entryPath = path.resolve(__dirname, "src", "modules"),
entryPoints = {
vendor: ["babel-polyfill", "react", "react-dom", "react-pure-render", "react-simpletabs", "react-redux", "redux", "redux-thunk"],
a: entryPath + "/a.js",
b: entryPath + "/b.js",
c: entryPath + "/c.js",
d: entryPath + "/d.js",
...
}, plugins = [
new CommonsChunkPlugin({
name: "commons",
filename: "commons.bundle.js",
minChunks: 2,
chunks: Object.keys(entryPoints).filter(key => key !== "vendor")
}),
new CommonsChunkPlugin("vendor", "vendor.bundle.js"),
new ExtractTextPlugin("[name].bundle.css", {
//allChunks: true
})
];
por lo que este código de arriba a la izquierda en b.bundle.js sigue siendo una importación importante de React y otras bibliotecas React. después de agregar "tabla de datos fijos" a la lista de proveedores, eso desapareció y el único código fuente de reacción que hubo fue en vendor.bundle.js ¿Supongo que eso es lo que estaba buscando? (al final, cada proveedor que no figura en la lista de proveedores terminó en cada módulo.bundle.js propio o en commons.bundle.js si se reutilizó en varios paquetes)
Saludos Jonas