I have problem with providing jQuery as var to global scope for legacy js code.
main.js
var $ = require('jquery');
window.$ = window.jQuery = $;
webpack-config.js
var Encore = require('@symfony/webpack-encore');
Encore
// directory where all compiled assets will be stored
.setOutputPath('mainsites/build/')
// what's the public path to this directory (relative to your project's document root dir)
.setPublicPath('/build')
// empty the outputPath dir before each build
.cleanupOutputBeforeBuild()
// will output as web/build/app.js
.addEntry('app', './assets/js/main.js')
// allow legacy applications to use $/jQuery as a global variable
.autoProvidejQuery()
.enableSourceMaps(!Encore.isProduction())
// create hashed filenames (e.g. app.abc123.css)
.enableVersioning()
;
// export the final configuration
module.exports = Encore.getWebpackConfig();
package.js
{
"name": "schoolm",
"version": "0.0.1",
"license": "UNLICENSED",
"private": true,
"dependencies": {
"jquery": "^2.1.4",
},
"devDependencies": {
"@symfony/webpack-encore": "github:symfony/webpack-encore"
}
}
html
<?php
$webpackConfig = json_decode(file_get_contents(__DIR__ . '/../mainsites/build/manifest.json'), true);
?>
<script src="<?php echo $webpackConfig['build/app.js']; ?>"></script>
chrome console
> jQuery
VM117:1 Uncaught ReferenceError: jQuery is not defined
at <anonymous>:1:1
(anonymous) @ VM117:1
> $
function ( selector, context ) {
// The jQuery object is actually just the init constructor 'enhanced'
// Need init if jQuery is called (just allow error to be thrown if not included)
return new jQuery.…
@gimler this should be fixed by https://github.com/symfony/webpack-encore/pull/10
@alOneh doesn't work
also try this
// .autoProvidejQuery()
.autoProvideVariables({
$: 'jquery',
jQuery: 'jquery',
'window.jQuery': 'jquery'
})
in the generated js file
/* WEBPACK VAR INJECTION */(function(__webpack_provided_window_dot_jQuery) {// loads the jquery package from node_modules
var $ = __webpack_require__("./node_modules/jquery/dist/jquery.js");
window.$ = $;
__webpack_provided_window_dot_jQuery = $;
/* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__("./node_modules/jquery/dist/jquery.js")))
Looks weird to me that there is nothing about jQuery itself in the generated code.
regarding window.jQuery, I had a doubt about it from the start. I don't think Webpack allows names containing dots when providing variables.
but as provided globals are exposed on window already (see window.$ = $), we should not need the window.jQuery. We only need to make the jQuery case work fine
hmm, I think I understood by looking at the generated file: autoprovided variables may be replacing window.jQuery by __webpack_provided_window_dot_jQuery in the processed source code (and ensuring it is initialized properly). It does not define a global variable for other code not processed by webpack.
Can you try writing your main.js code like this:
var $ = require('jquery');
window.$ = $;
window.jQuery = $;
Maybe webpack will recognize that window.jQuery is used for an assignment here rather than reading a variable.
Maybe webpack will recognize that window.jQuery is used for an assignment here rather than reading a variable.
I think this is correct. We use ProvidePlugin. And I think when you have window.$ = window.jQuery = $;, it thinks that window.jQuery is an undefined variable that you are trying to use (so it replaces it), where obviously it's actually an assignment.
@gimler let us know if the change @stof suggested fixes it. Then we can see if there's anything we can do about it (seems like a possible bug in the ProvidePlugin ).
doesn't work
var $ = require('jquery');
window.jQuery = require('jquery');
window.$ = window.jQuery;
and also
var $ = require('jquery');
window.$ = $;
window.jQuery = $;
var $ = require('jquery');
window.jQuery = require('jquery');
window.$ = window.jQuery;
it replace the window.jQuery everytime with __webpack_provided_window_dot_jQuery.
Ok got it to work. When using window.jQuery you must remove the .autoProvidejQuery() from webpack config.
main.js
// loads the jquery package from node_modules
var $ = require('jquery');
window.$ = $;
window.jQuery = $;
webpack.config.js
var Encore = require('@symfony/webpack-encore');
Encore
// directory where all compiled assets will be stored
.setOutputPath('mainsites/build/')
// what's the public path to this directory (relative to your project's document root dir)
.setPublicPath('/build')
// empty the outputPath dir before each build
.cleanupOutputBeforeBuild()
// will output as web/build/app.js
.addEntry('app', './assets/js/main.js')
.enableSourceMaps(!Encore.isProduction())
// create hashed filenames (e.g. app.abc123.css)
.enableVersioning()
;
// export the final configuration
module.exports = Encore.getWebpackConfig();
@gimler you need to explicitly expose the jQuery variables. To do so:
1/ you need to install the expose-loader
2/ update you webpack config
// webpack.config.js
Encore
// ...
addLoader({
test: require.resolve('jquery'),
use: [{
loader: 'expose-loader',
options: 'jQuery'
},{
loader: 'expose-loader',
options: '$'
}]);
@weaverryan what about having a exposeJquery() method ?
yeah, auto providing variables for files processed by jQuery is not the same than exposing global variables outside the asset processed by webpack.
I'm conflicted. Exposing global variables via window.jQuery = ... is a really nice, straightforward, non-abstracted way of adding global variables. It can be done in your code and it is done in your code, and I like that.
An alternative is to remove window.jQuery from autoProvidejQuery(). @alOneh you added this in #10, and it is somewhat common to see this. How common is it for a library to reference window.jQuery internally? I'd kinda prefer to remove it... and document how to fix those libraries - i.e. by setting window.jQuery = $ before requiring the library (we could even doc to unset it after). It's a bit hacky... but this is already a hacky situation, and I don't know if we should add more layers to solve it.
See #46
@weaverryan the issue is the part before requiring the library in your proposal, as it might be hard to identify the first place triggering the loading of this library in a big project
Let me precise some things about Webpack and Jquery.
ProvidePlugin is use to expose to all module the provided variables, so the provided variables or not expose globally.
If we want to make jquery available everywhere we need to expose it explicitly as say in my previous comment. If we remove the window.jQuery line from ProvidePlugin, we will break the use of third party like bootstrap.
If @gimler have some legacy code with in-page javascript, the fix is to expose jquery otherwise we don't need to make the fix propose by @weaverryan.
@gimler another solution: define the global variable like this:
// main.js
// loads the jquery package from node_modules
var $ = require('jquery');
global.$ = $;
global.jQuery = $;
in the CommonJS world, the way to access the global scope is global
The actual version of encore works for me see my comment https://github.com/symfony/webpack-encore/issues/32#issuecomment-309646363 above.
Also the version from @stof global.* instate of window.* works booth.
I use jquery bootstrap and a bunch of other jquery plugins. Also some legacy code that use jquery.
In the console i also get $ and jQuery.
So i don't need the .autoProvidejQuery() or .autoProvideVariables() method. only the two lines in my entry script after loading jquery.
@gimler .autoProvidejQuery is here to provide jQuery to other files loaded though webpack, without the need to define global variables (and without the need to ensure that you expose it soon enough)
I'm going to propose to re-add window.jQuery to autoProvidejQuery(). But, here is a good workaround:
global.$ = global.jQuery = require('jquery');
This will do the same as window.$ = window.jQuery = require('jquery');, but doesn't suffer from the problem described in this issue :).
This process is quite annoying to be honest. I am frustrated at how unstable this whole process is. Exposing "$" seems to be such a mess using encore. I wish someone could publish a way for this to actually work. It works, then one small change and it stops.
@earlfaneuf The process described in the doc should be quite stable now, what kind of changes are you talking about?
Also, unless you're working on a legacy app I'd recommend you not to expose things globally (including jQuery), it causes more problems than it solves in the long run.
Why is this closed this is still a serious issue. I have followed all of the docs, links info I can find and none of it works. I still get $ not defined. This, this right here. https://symfony.com/doc/current/frontend/encore/legacy-applications.html that doesn't work. I'd like to know who that worked for and how? Is there any way to get Webpack working or should I just remove that garbage and find something that ACTUALLY WORKS.
@AkashicSeer please open an new issue (commenting on an issue closed 3 years ago for something which might not even be the same issue is a bad idea) with more details about the code that triggers the error (including how you use webpack-encore and where the undefined $ is).
I have the same problem. None of the described ways are working.
@Deltachaos my comment appearing just above yours also applies to you
Most helpful comment
Ok got it to work. When using
window.jQueryyou must remove the.autoProvidejQuery()from webpack config.main.js
webpack.config.js