Je pense que cela devrait être plus simple qu’il ne l’est. Je dois accéder à toutes mes bibliothèques javascript depuis le frontend et, comme je l’intègre dans un ancien système, je ne peux pas appeler require("bundle.js");
depuis le frontend. Tout dans la portée globale des fichiers fournis doit être accessible à partir de la portée globale de la page frontale en les important via la balise <script>
.
J'ai donc besoin de changer l'ancien:
<script src="js/jquery.js"></script>
<script src="js/silly.js"></script>
<script>
$(silly()); // Some function in silly.js's global scope
</script>
Pour le nouveau:
<script src="js/bundle.js"></script>
<script>
$(silly()); // Some function in silly.js's global scope
</script>
expose-loader: Cela fonctionnerait totalement si je n'avais pas 100 variables globales que je ne veux pas explicitement lui demander de rechercher .
ProvidePlugin: Laisse uniquement les bibliothèques voir les autres bibliothèques. Je ne peux pas non plus écrire explicitement tous les globals dont j'ai besoin avec ma configuration actuelle (d'autres sont ajoutés en permanence).
Donc, pour plus de clarté, j'ai besoin que mon webpack.config.js
ressemble à l'une de ces options:
// Everything is wrapped in module.exports and other irrelevant things
plugins: [
new StaticLibraryMergerSuperNeatPlugin("js/*.js")
]
// ...
Ou:
rules: [
{
test: /\.js$/,
use: [
"neat-merging-cool-loader",
"babel-loader"]
}
]
// ...
Y a-t-il une solution évidente qui me manque?
Tl; Dr: Comment puis-je créer des globales à partir de mes fichiers js fournis, être exposé à la portée globale lors de l'importation sur une page html frontale via <script src="js/bundle.js"></script>
?
Btw: Si quelqu'un est une légende de WebPack et sait pourquoi c'est une mauvaise approche, postez-le ci-dessous avec une brève explication afin que je puisse réparer ma vie.
_ {Remarque: ce n'est pas le scénario idéal, mais comme j'ai un nombre constant de nouveaux globals ajoutés, il me fallait créer un plugin pour intégrer mon code javascript.} _
Ceci empile simplement votre code pour être inclus dans l'interface. Voici mon exemple d'utilisation:
De l'ancien:
<script src="js/jquery.js"></script>
<script src="js/silly.js"></script>
<script>
$(silly()); // Some function in silly.js's global scope
</script>
Pour le nouveau:
<script src="js/bundle.js"></script>
<script>
$(silly()); // Some function in silly.js's global scope
</script>
var RawBundlerPlugin = require('webpack-raw-bundler');
module.exports = {
plugins: [
new RawBundlerPlugin({
excludedFilenames: [/angulartics/],
readEncoding: "utf-8",
includeFilePathComments: false,
bundles: [ "vendor.js", "styles.css" ],
"vendor.js": [
'js/*.js'
],
"styles.css": [
'css/bootstrap.css',
'css/edits.css'
]
})
]
}
Un avertissement juste:
Cela ne devrait pas être votre solution idéale, mais j’ai eu un mauvais cas qui en a fait l’option la plus simple. Utiliser expose-loader
et import
ou window['module'] = require('module.js')
est bien plus sûr car c’est autour de quoi a été construit le webpack. Cependant, si vous avez des maux de tête et que vous voulez juste un simple bundler, n'hésitez pas à utiliser ce plugin.
Voici un exemple de la façon dont je le fais sur mon propre site. Je ne sais pas si c'est le seul moyen, ni même le meilleur, mais c'est propre, simple et cela fonctionne pour moi.
Note latérale importante - Utilisez window["propName"]
lors de la déclaration de choses dans la fenêtre, car si vous exécutez webpack -p
, les valeurs qui ne sont pas des chaînes sont uglifiées. Ainsi, si vous le définissez comme window.propName
, il peut être remplacé par s.c
et le reste de vos caractères. le code ne sait pas ce que c'est. Le déclarer avec la notation entre crochets en tant que chaîne forcera webpack à conserver le nom intact afin que vous puissiez y accéder depuis n'importe quel endroit portant le même nom.
site.ts (peut être .js, peu importe)
/*************************/
/*** JQUERY + JQUERYUI ***/
/*************************/
/* var declaration for TypeScript - not needed if not using .ts */
declare var $:JQueryStatic; declare var jQuery:JQueryStatic;
window["$"] = window["jQuery"] = require("jquery");
require("jquery-ui/effects/effect-slide");
require("jquery-ui/widgets/autocomplete");
require("jquery-ui/widgets/button");
require("jquery-ui/widgets/datepicker");
require("jquery-ui/widgets/tooltip");
/*************************/
/* END JQUERY + JQUERYUI */
/*************************/
/***************/
/*** ANGULAR ***/
/***************/
/* var declaration for TypeScript - not needed if not using .ts */
declare var angular:ng.IAngularStatic;
window["angular"] = require("angular");
require("angular-sanitize");
/***************/
/* END ANGULAR */
/***************/
/************************/
/*** MISC THIRD-PARTY ***/
/************************/
window["moment"] = require("moment");
window["saveAs"] = require("FileSaver").saveAs;
window["JSZip"] = require("jszip");
/************************/
/* END MISC THIRD-PARTY */
/************************/
/* var declaration for TypeScript - not needed if not using .ts */
declare var globals:Globals;
window["globals"] = require("./globals");
Layout.html (chargé sur chaque page)
.....
<script src="/dist/scripts/site.bundle.js"></script>
.....
webpack.config.js
var path = require('path');
var resolve = path.resolve;
var AssetsPlugin = require('assets-webpack-plugin');
var WebpackCleanupPlugin = require("webpack-cleanup-plugin");
'use strict';
var babelOptions = {
"presets": [
[
"es2015",
{
"modules": false
}
],
"es2016"
]
};
module.exports = [{
cache: true,
context: resolve('Scripts'),
devtool: "source-map",
entry: {
site: './site.ts',
},
output: {
path: path.resolve(__dirname, './dist/scripts'),
filename: '[name].bundle.js',
},
module: {
rules: [{
test: /\.ts$/,
exclude: /node_modules/,
use: [
{
loader: 'babel-loader',
options: babelOptions
},
{
loader: 'ts-loader'
}
]
}, {
test: /\.js$/,
exclude: /node_modules/,
use: [
{
loader: 'babel-loader',
options: babelOptions
}
]
}]
},
plugins: [
new AssetsPlugin({ path: path.resolve(__dirname, './dist/assets') }),
new WebpackCleanupPlugin({})
],
}];
Si vous utilisez webpack 2.x, il existe un plugin intégré
Vous définissez la variable globale et vous pourrez y accéder.
plugins: [
new webpack.ProvidePlugin({
$: "jquery",
jQuery: "jquery",
"window.jQuery": "jquery",
"window.Tether": 'tether',
"Tether": 'tether'
}),
...
]
voici ma config complète
var webpack = require("webpack");
var ExtractTextPlugin = require("extract-text-webpack-plugin");
var path = require("path")
module.exports = {
entry: "./src/entry-js.js",
devtool: 'source-map',
output: {
path: path.join(__dirname, "/public/dist/js"),
publicPath: "/public/",
filename: 'bundle.js',
chunkFilename: 'chunk.[name].[id].js',
},
module: {
rules: [
{
test: /\.js$/,
loader: "babel-loader",
options: {
presets: ["es2015", "stage-0"]
},
exclude: [
path.resolve(__dirname, "node_modules")
],
},
{
test: /\.css$/,
use: ExtractTextPlugin.extract({
fallback: "style-loader",
use: "css-loader"
})
},
{
test: /\.(scss|sass)$/,
use: ExtractTextPlugin.extract({
fallback: "style-loader",
use: [
"css-loader",
"sass-loader"
]
})
},
{
test: /\.less$/,
use: ExtractTextPlugin.extract({
fallback: "style-loader",
use: [
"css-loader",
"less-loader"
]
})
},
{
test: /\.(png|svg|jpg|gif)$/,
use: [{
loader:"file-loader",
options: {
limit: 500,
name: "../img/[name].[ext]"
}
}]
},
{
test: /\.(woff|woff2|eot|ttf|otf)$/,
use: [{
loader:"file-loader",
options: {
limit: 500,
name: "../fonts/[name].[ext]"
}
}]
}
]
},
plugins: [
new ExtractTextPlugin({
filename: "../css/bundle.css",
disable: false,
allChunks: true
}),
new webpack.ProvidePlugin({
$: "jquery",
jQuery: "jquery",
"window.jQuery": "jquery",
"window.Tether": 'tether',
"Tether": 'tether'
})
]
};
Voici mon fichier d'entrée
/********************
* CSS Libraries *
********************/
// normalize v7
import "../node_modules/normalize.css/normalize.css";
// bootstrap v4.alpha-5
import "../node_modules/bootstrap/scss/bootstrap.scss";
/******************
* CSS Custom *
******************/
import "./css/main.css";
import "./sass/main.scss";
/********************
* JS Libraries *
********************/
//Jquery v3.2.1
import '../node_modules/jquery/src/jquery.js';
import Tether from 'tether';
//Bootstrap v4-alpha-5
import "../node_modules/bootstrap/dist/js/bootstrap.min.js";
import "./js/main.js";
J'ai eu le même problème et la meilleure solution que j'ai trouvée consiste à utiliser webpack-concat-plugin .
Ce qu'il fait:
La seule chose qu’il ne fait pas est de ne pas laisser tous les globals s’échapper à la portée globale.