webpack symfony encore jquery third party plugins - symfony

i am having problem with implementing jquery 3rd party plugins in symfony webpack encore.
so far i have several .js files with varous logic, and also some scripts inside twig files that execute some of js.
this is app.js :
var $ = require('jquery');
global.$ = global.jQuery = global.jquery = $;
require('jquery-validation');
webpack compiles, but when i execute program i get:
$(...).validate is not a function
webpack.config.js is straightforward:
var Encore = require('#symfony/webpack-encore');
Encore
// directory where compiled assets will be stored
.setOutputPath('public/build/')
// public path used by the web server to access the output path
.setPublicPath('/build')
.setManifestKeyPrefix('build/')
.addEntry('base', './assets/js/base.js')
.splitEntryChunks()
.enableSingleRuntimeChunk()
;
module.exports = Encore.getWebpackConfig();
package.json:
"jquery": "^3.3.1",
"jquery-validation": "^1.18.0",
"jquery-datetimepicker": "^2.5.20",
update:
jquery-datetimepicker is working fine,
but jquery-validation is not!

solution:
update webpack.config.js with alias information, so that every jquery 3rd party plugin uses same jquery
var path = require('path');
Encore
.addAliases({
'jquery': path.join(__dirname, 'node_modules/jquery/src/jquery')
})

from: https://symfony.com/doc/current/frontend/encore/legacy-apps.html
jQuery Plugins and Legacy Applications
Inside Webpack, when you require a module, it does not (usually) set a global variable. Instead, it just returns a value:
// this loads jquery, but does *not* set a global $ or jQuery variable
const $ = require('jquery');
...
Fixing jQuery Plugins that Expect jQuery to be Global
jQuery plugins often expect that jQuery is already available via the $ or jQuery global variables. To fix this, call autoProvidejQuery() from your webpack.config.js file:
Encore
// ...
.autoProvidejQuery() // add this line into your webpack.config.js file
;
Accessing jQuery from outside of Webpack JavaScript Files
If your code needs access to $ or jQuery and you are inside of a file that's processed by Webpack/Encore, you should remove any "$ is not defined" errors by requiring jQuery: var $ = require('jquery').
But if you also need to provide access to $ and jQuery variables outside of JavaScript files processed by Webpack (e.g. JavaScript that still lives in your templates), you need to manually set these as global variables in some JavaScript file that is loaded before your legacy code.
For example, in your app.js file that's processed by Webpack and loaded on every page, add:
// require jQuery normally
const $ = require('jquery');
+ // create global $ and jQuery variables
+ global.$ = global.jQuery = $;

Related

#Babylonjs (ES6) in Nextjs failes with unexpected token 'export'

I'm building my website with Nextjs and importing Bablyonjs was throwing up the following error.
syntaxError: Unexpected token 'export'
module.exports = require("#babylonjs/core")
I'm using the standard nextjs setup with tsconfig.json
I'm refering to this Babylon documentation and using the examples verbatim.
https://doc.babylonjs.com/extensions/Babylon.js+ExternalLibraries/BabylonJS_and_ReactJS
https://doc.babylonjs.com/divingDeeper/developWithBjs/treeShaking
After a not so insignificant amount of time searching i finally learned the following.
#babylon (es6) is not compiled into javascript and is instead nicely defined (es6) typescript friendly library of source code. (helps when wanting to treeshake)
Nextjs out of the box isn't configured to compile anything in node_modules. It expects precompiled javascript ready to consume.
Point 2. is why i received the error, nextjs was expecting compiled js and it was getting uncompiled source.
To fix this you need to add a next.config.js and configure it with next-transpile-modules and next-compose-plugins.
yarn add next-transpile-modules
yarn add next-compose-plugins
next.config.js
//const withTM = require('next-transpile-modules')(['#babylonjs']);
const withTM = require('next-transpile-modules')(['#babylonjs/core']); // As per comment.
const withPlugins = require('next-compose-plugins');
const nextConfig = {
target: 'serverless',
webpack: function (config) {
/// below is not required for the problem described. Just for reference.(es6)
config.module.rules.push({test: /\.yml$/, use: 'raw-loader'})
return config
}
}
module.exports = withPlugins([withTM], nextConfig);
It compiled without error after this.
References
Handy links i came across solving this issue.
https://github.com/vercel/next.js/issues/706
https://www.npmjs.com/package/next-transpile-modules
https://www.npmjs.com/package/next-compose-plugins
https://www.typescriptlang.org/tsconfig
https://doc.babylonjs.com/divingDeeper/developWithBjs/treeShaking
https://doc.babylonjs.com/extensions/Babylon.js+ExternalLibraries/BabylonJS_and_ReactJS
Links that helped some on the way to understanding the problem.
Test ES6 modules with Jest
https://forum.babylonjs.com/t/jest-is-crashing/12557/7
https://github.com/MichalLytek/type-graphql/issues/689
For Next.js 11, I had to slightly revise the answer from Emile:
Install the following package:
yarn add next-transpile-modules
In your next.config.js file add the following:
const withTM = require('next-transpile-modules')(["package2", "package2"]);
module.exports = withTM({
reactStrictMode: true
})
Put assets folder inside public folder. To access assets can be done by calling full path url.
await SceneLoader.Append(
'http://localhost:3000/assets/characters/avatar.glb'
);

Symfony 4 & encore autorefresh does not work, I always have to reload manually my browser

From a new Symfony 4 project, when I run this command :
./node_modules/.bin/encore dev-server --hot
And then I modify a scss file (change the the body tag background-color by example), the shell react
But my browser does not automatically refresh ! I always have to reload manually the page for see the latest css change. Where may I do a mystake ?
Thank you !
=> I tested with different browsers
=> If I modify a custom javascript file, the browser autorefresh ! in contrary when I change the scss file
=> My assets directory structure :
=> My webpack.config.js content :
var Encore = require('#symfony/webpack-encore');
Encore
// directory where compiled assets will be stored
.setOutputPath('public/build/')
// public path used by the web server to access the output path
.setPublicPath('/build')
// only needed for CDN's or sub-directory deploy
//.setManifestKeyPrefix('build/')
/*
* ENTRY CONFIG
*
* Add 1 entry for each "page" of your app
* (including one that's included on every page - e.g. "app")
*
* Each entry will result in one JavaScript file (e.g. app.js)
* and one CSS file (e.g. app.css) if you JavaScript imports CSS.
*/
.addEntry('app', './assets/js/app.js')
.addEntry('article/main', './assets/js/article/main.js')
.addStyleEntry('article/style','./assets/css/article/style.scss')
//.addEntry('page2', './assets/js/page2.js')
/*
* FEATURE CONFIG
*
* Enable & configure other features below. For a full
* list of features, see:
* https://symfony.com/doc/current/frontend.html#adding-more-features
*/
.cleanupOutputBeforeBuild()
.enableBuildNotifications()
.enableSourceMaps(!Encore.isProduction())
// enables hashed filenames (e.g. app.abc123.css)
.enableVersioning(Encore.isProduction())
// enables Sass/SCSS support
.enableSassLoader()
// uncomment if you use TypeScript
//.enableTypeScriptLoader()
// uncomment if you're having problems with a jQuery plugin
//.autoProvidejQuery()
;
module.exports = Encore.getWebpackConfig();
=> And my automatically generated public/build/manifest.json file :
considering the documentation here the Hot Module Replacement (HMR) doesn't work for everything at the moment. It should work for Vue.js but that's all.
For more informations you can check the documentation for HMR.
TL:DR Your custom js & css assets are not supposed to be hot reloaded in the current state of HMR. You'll have to reload your browser manually. I don't know if you know about the --watch option, but it'll allow you to compile your code every time a file has changed.
Good luck

VueJS webpack build error SCSS related

I'm having errors when I try to build my VueJS project with the style sheets.
My error when I run "yarn run dev --watch" produces these errors:
c:\wamp\www\DBViewer2>yarn run dev --watch
yarn run v1.6.0
warning package.json: No license field
$ encore dev --progress=true --watch
Running webpack ...
0% compiling
Webpack is watching the files…
95% emitting ERROR Failed to compile with 1 errors 16:00:56
This dependency was not found:
* !!vue-style-loader!css-loader?sourceMap!../node_modules/vue-loader/lib/style-compiler/index?{"optionsId":"0","vue":true,"scoped":false,"sourceMap":true}!scss-loader!../node_modules/vue-loader/lib/selector?type=styles&index=0!./App.vue in ./assets/App.vue
To install it, you can run: npm install --save !!vue-style-loader!css-loader?sourceMap!../node_modules/vue-loader/lib/style-compiler/index?{"optionsId":"0","vue":true,"scoped":false,"sourceMap":true}!scss-loader!../node_modules/vue-loader/lib/selector?type=styles&index=0!./A
I'm not sure what is causing this. It appears it is looking for the files in the wrong location?
Here is my App.vue file:
<template>
<router-view></router-view>
</template>
<script>
export default {
name: 'app'
}
</script>
<style lang="scss-loader">
/* Import Font Awesome Icons Set */
$fa-font-path: 'font-awesome/fonts/';
#import 'font-awesome/scss/font-awesome.scss';
/* Import Simple Line Icons Set */
$simple-line-font-path: 'simple-line-icons/fonts/';
#import 'simple-line-icons/scss/simple-line-icons.scss';
/* Import Bootstrap Vue Styles */
#import 'bootstrap-vue/dist/bootstrap-vue.css';
/*// Import Main styles for this application*/
#import './assets/scss/style';
</style>
Here is my webpack.config.js:
var Encore = require('#symfony/webpack-encore');
Encore
// the project directory where all compiled assets will be stored
.setOutputPath('public_html/build/')
// the public path used by the web server to access the previous directory
.setPublicPath('/build')
// will create public/build/app.js and public/build/app.css
.addEntry('main', './assets/main.js')
.addEntry('vendor', './assets/js/vendor.js')
// allow legacy applications to use $/jQuery as a global variable
.autoProvidejQuery()
// enable source maps during development
.enableSourceMaps(!Encore.isProduction())
// empty the outputPath dir before each build
.cleanupOutputBeforeBuild()
// show OS notifications when builds finish/fail
.enableBuildNotifications()
// create hashed filenames (e.g. app.abc123.css)
// .enableVersioning()
.enableVueLoader()
// allow sass/scss files to be processed
.enableSassLoader()
;
// export the final configuration
module.exports = Encore.getWebpackConfig();
Any suggestions is greatly appreciated. Have spent 2 days now trying different things and research on google. I'm just not familiar enough with symfony/encore and this is my first vuejs project.
In order to be able to use SCSS in a Vue template, you need to declare in the single file component the following style block:
<!-- Those styles are not scoped to that particular component -->
<style lang="scss">...</style>
<!-- Or those styles are scoped to that particular component -->
<style lang="scss" scoped>...</style>
You can even use both in the same file, if needed.
You'll also need to install the correct node dependencies by running:
npm install --dev node-sass sass-loader
This should then work out of the box when used in a project initialized with vue-cli.
However you could need to add this in your webpack 'test' configuration to make lang="scss" work in tests when using vue-loader's ?inject option:
resolveLoader: {
alias: {
'scss-loader': 'sass-loader',
},
},

Symfony Webpack Encore, Multiple JS/CSS Files to one file

I want to create one css/js file from multiple css/js files. Multiple addEntry not working, please check my code and give me the solution.
var Encore = require('#symfony/webpack-encore');
Encore
// the project directory where compiled assets will be stored
.setOutputPath('web/build/')
// the public path used by the web server to access the previous directory
.setPublicPath('/build')
.cleanupOutputBeforeBuild()
.enableSourceMaps(!Encore.isProduction())
// uncomment to create hashed filenames (e.g. app.abc123.css)
.enableVersioning(Encore.isProduction())
// uncomment for legacy applications that require $/jQuery as a global variable
//.autoProvidejQuery()
// uncomment to define the assets of the project
.addEntry('js/app', './assets/js/app.js')
.addEntry('js/uploader', './assets/js/uploader.js')
.addStyleEntry('css/icons', './assets/css/icons.scss')
.addStyleEntry('css/app', './assets/css/app.scss')
.addStyleEntry('css/uploader', './assets/css/uploader.scss')
// uncomment if you use Sass/SCSS files
.enableSassLoader()
.enableBuildNotifications();
module.exports = Encore.getWebpackConfig();
And add common jQuery and after adding the js files some function is undefined, why?
You only need one addEntry call. The solution I use to do that is to create a main.js file where I import all the file. Something like this for example:
// CSS
import 'bootstrap/dist/css/bootstrap.min.css';
import './global.css';
import './easy-autocomplete.custom.css';
// JS
const $ = require('jquery/dist/jquery.min');
const jQuery = $;
import 'bootstrap';
import 'jscroll/jquery.jscroll';
import 'easy-autocomplete';
import './global.js';
And then you can use this file in your addEntry like this:
.addEntry('app', './assets/main.js')
After running Encore, you will get a web/build/app.js file and web/build/app.css file
Multiple .addStyleEntry will create multiple files. You can pass an array into .addStyleEntry to make a single css file out of multipe css/sass/less files like:
.addStyleEntry('style', ['./src/sass/style.scss', './node_modules/swiper/dist/css/swiper.css'])
This will create a style.css. The order of the array entries matches the output in the css file.

Symfony Webpack/Encore processing unreferenced source images

I am attempting to get Webpack to process and copy all the image files in src folder and output them to the build folder using ‘image-webpack-loader`.
As far as I understand, Webpack will only do this with images referenced in CSS/SASS/LESS or an entry point.
I am working on a Symfony project and have many references in twig templates, which are obviously ignored.
Any idea how I could make this happen without the addition of a build tool or making a duplicate reference file for every image that I include in a project template?
Create a s subdirectory under web root:
Symfony 3:
web/s
Symfony 4 & 5:
public/s
Configure your new subdomain:
Symfony 3: (app/config/config.yml)
framework:
assets:
base_urls:
- '%protocol%://s.%host%'
Symfony 4 & 5: (config/packages/assets.yaml)
framework:
assets:
base_urls:
- '%protocol%://s.%host%'
Note:
%protocol% is either http or https accoring to you environment
%host% is your host, maybe example.com or something.
Configure Webpack (webpack.config.js)
Symfony 3:
var Encore = require('#symfony/webpack-encore');
Encore
// ...
.setOutputPath('./web/s/build/')
.setPublicPath('/build')
.setManifestKeyPrefix('build')
.cleanupOutputBeforeBuild()
// ...
;
module.exports = Encore.getWebpackConfig();
Symfony 4 & 5:
var Encore = require('#symfony/webpack-encore');
Encore
// ...
.setOutputPath('./public/s/build/')
.setPublicPath('/build')
.setManifestKeyPrefix('build')
.cleanupOutputBeforeBuild()
// ...
;
module.exports = Encore.getWebpackConfig();
Put all your images inside /web/s or /public/s according to your Symfony version.
Inside your Twig views, access them like below:
<img src="{{ asset('photo.jpg') }}" alt="Photo"/>
Accept and hit upvote on this cool answer!
In webpack.config.js, you could add .copyFiles() to the Encore object. This will take an object with "from", and "to" keys, with a couple of wildcards.
Here is an example:
.copyFiles({
from: 'src',
to: 'images/[path][name].[ext]'
})

Resources