Closed phifa closed 5 years ago
cc @kball By the way myself also interested for knowing the answer to it ;)
The latter is how I'd do it - will set up a sample project and verify exact config for you
Fancybox expects window.jQuery
to be defined. There also appears to be some sort of inconsistency when using an es6 import given it's not an es6 module, so I used a node style require
instead (webpack groks both). In the end this is what it took to get this to work in my app.js:
window.jQuery = $;
require('@fancyapps/fancybox/dist/jquery.fancybox');
Thanks @kball. Wouldn't it make sense to restructure things a little bit? Maybe like so:
This is what my app.js now looks like:
// Framework
import $ from 'jquery';
import whatInput from 'what-input';
import './lib/foundation-explicit-pieces';
// User
require('./lib/fancybox');
require('./lib/justifiedGallery');
require('./lib/classie');
require('./lib/header');
require('./lib/counter');
This is my lib/foundation-explicit-pieces.js
:
import $ from 'jquery';
window.$ = $;
import { Foundation } from 'foundation-sites/js/foundation.core';
import { rtl, GetYoDigits, transitionend } from 'foundation-sites/js/foundation.util.core';
import { Box } from 'foundation-sites/js/foundation.util.box'
import { onImagesLoaded } from 'foundation-sites/js/foundation.util.imageLoader';
import { Keyboard } from 'foundation-sites/js/foundation.util.keyboard';
import { MediaQuery } from 'foundation-sites/js/foundation.util.mediaQuery';
import { Motion, Move } from 'foundation-sites/js/foundation.util.motion';
import { Nest } from 'foundation-sites/js/foundation.util.nest';
import { Timer } from 'foundation-sites/js/foundation.util.timer';
import { Touch } from 'foundation-sites/js/foundation.util.touch';
import { Triggers } from 'foundation-sites/js/foundation.util.triggers';
import { Abide } from 'foundation-sites/js/foundation.abide';
import { Accordion } from 'foundation-sites/js/foundation.accordion';
import { AccordionMenu } from 'foundation-sites/js/foundation.accordionMenu';
import { Drilldown } from 'foundation-sites/js/foundation.drilldown';
import { Dropdown } from 'foundation-sites/js/foundation.dropdown';
import { DropdownMenu } from 'foundation-sites/js/foundation.dropdownMenu';
import { Equalizer } from 'foundation-sites/js/foundation.equalizer';
import { Interchange } from 'foundation-sites/js/foundation.interchange';
import { Magellan } from 'foundation-sites/js/foundation.magellan';
import { OffCanvas } from 'foundation-sites/js/foundation.offcanvas';
import { Orbit } from 'foundation-sites/js/foundation.orbit';
import { ResponsiveMenu } from 'foundation-sites/js/foundation.responsiveMenu';
import { ResponsiveToggle } from 'foundation-sites/js/foundation.responsiveToggle';
import { Reveal } from 'foundation-sites/js/foundation.reveal';
import { Slider } from 'foundation-sites/js/foundation.slider';
import { SmoothScroll } from 'foundation-sites/js/foundation.smoothScroll';
import { Sticky } from 'foundation-sites/js/foundation.sticky';
import { Tabs } from 'foundation-sites/js/foundation.tabs';
import { Toggler } from 'foundation-sites/js/foundation.toggler';
import { Tooltip } from 'foundation-sites/js/foundation.tooltip';
import { ResponsiveAccordionTabs } from 'foundation-sites/js/foundation.responsiveAccordionTabs';
Foundation.addToJquery($);
// Add Foundation Utils to Foundation global namespace for backwards compatibility.
Foundation.rtl = rtl;
Foundation.GetYoDigits = GetYoDigits;
Foundation.transitionend = transitionend;
Foundation.Box = Box;
Foundation.onImagesLoaded = onImagesLoaded;
Foundation.Keyboard = Keyboard;
Foundation.MediaQuery = MediaQuery;
Foundation.Motion = Motion;
Foundation.Move = Move;
Foundation.Nest = Nest;
Foundation.Timer = Timer;
// Touch and Triggers previously were almost purely sede effect driven, so no // need to add it to Foundation, just init them.
Touch.init($);
Triggers.init($, Foundation);
Foundation.plugin(Abide, 'Abide');
Foundation.plugin(Accordion, 'Accordion');
Foundation.plugin(AccordionMenu, 'AccordionMenu');
Foundation.plugin(Drilldown, 'Drilldown');
Foundation.plugin(Dropdown, 'Dropdown');
Foundation.plugin(DropdownMenu, 'DropdownMenu');
Foundation.plugin(Equalizer, 'Equalizer');
Foundation.plugin(Interchange, 'Interchange');
Foundation.plugin(Magellan, 'Magellan');
Foundation.plugin(OffCanvas, 'OffCanvas');
Foundation.plugin(Orbit, 'Orbit');
Foundation.plugin(ResponsiveMenu, 'ResponsiveMenu');
Foundation.plugin(ResponsiveToggle, 'ResponsiveToggle');
Foundation.plugin(Reveal, 'Reveal');
Foundation.plugin(Slider, 'Slider');
Foundation.plugin(SmoothScroll, 'SmoothScroll');
Foundation.plugin(Sticky, 'Sticky');
Foundation.plugin(Tabs, 'Tabs');
Foundation.plugin(Toggler, 'Toggler');
Foundation.plugin(Tooltip, 'Tooltip');
Foundation.plugin(ResponsiveAccordionTabs, 'ResponsiveAccordionTabs');
module.exports = Foundation;
$(document).foundation();
And this is for example my fancybox.js
:
import $ from 'jquery';
window.jQuery = $;
require('@fancyapps/fancybox/dist/jquery.fancybox');
$('a[data-fancybox="cl-group"]').fancybox({
baseClass: 'fancybox-custom-layout',
margin: 0
});
This way, the app.js
functions like the app.scss
and all JS is in separate files/modules.
@phifa I like that idea a lot - I think getting to a best practice with the new JS approach is going to take a little figuring, but this looks good to me.
@kball yeah, my solution is most likely not the best. I am not experienced with webpack at all, just trying to figure this out.
I think for foundation to succeed on the longrun, this is a critical topic to tackle. There are many guys like me out there using foundation, but have not been exposed to webpack. We cannot afford to loose them and we cannot afford to not win the newbies who are just starting out with web development. They will run to Bootstrap the minute they have the feeling it is easier to use - not because it's better.
By including webpack, we have added another layer of complexity to foundation. We need to lower all the entry barriers to get people on board. I think this is why I am proposing the above idea and I invite people with more experience and knowledge to improve upon the idea, like I said, this is most likely not the best solution/practise.
Also I noticed long transpiling time, sometimes a minute for webpack/babel/gulp to parse the JS files and reload the browsersync. I think it was @rafibomb that mentioned the speed gain through the use of webpack. Thus far, everything is slower than before.
@phifa would you like to submit a PR to the zurb stack with the new structure you proposed?
sure, no problem, do we want more eyes on this first, or you think it is a safe approach? also regarding transpile time? mabe you can test it first.
I've been building my own workflow for a week because just like when the javascript task was done with Gulp. The construction time seems a little tedious for a minute. This is not productive if you are developing.
Already with Gulp separate the structure into three directories:
This way when I changed something in Common or Main, Babel and concatenate took a second or even less.
I'm totally new to webpack, but I think you could move this to webpack. Here they speak of three methods:
Https://robertknight.github.io/posts/webpack-dll-plugins/
Of course this would be for development, unless it will make it easier to make a lazy load on Foundation users. So that you could have (Using DllPlugin or Code splitting ):
But there would have to be two Gulp tasks:
Const webpackConf = require ('../ conf / webpack.conf');
Const webpackDistConf = require ('../ conf / webpack-dist.conf');
Gulp.task ('webpack: dev', done => {
WebpackWrapper (false, webpackConf, done);
});
Gulp.task ('webpack: dist', done => {
Process.env.NODE_ENV = 'production';
WebpackWrapper (false, webpackDistConf, done);
});
Function webpackWrapper (watch, conf, done) {
Const webpackBundler = webpack (conf);
Const webpackChangeHandler = (err, stats) => {
If (err) {
GulpConf.errorHandler ('Webpack') (err);
}
Gutil.log (stats.toString ({
Colors: true,
Chunks: false,
Hash: false,
Version: false
}));
If (done) {
Done ();
Done = null;
} Else {
Browsersync.reload ();
}
};
If (watch) {
WebpackBundler.watch (200, webpackChangeHandler);
} Else {
WebpackBundler.run (webpackChangeHandler);
}
}
'Webpack: dev' -> vendor.bundle.js and main.bundle.js 'Webpack: dist' -> bundle.js
You can use the webpack ProvidePlugin to shim jQuery for older plugins. https://webpack.js.org/plugins/provide-plugin/ Then you can import any plugin you need as normal.
Hm, never had such issues with the current templates. Some jQuery plugins do not export the namespace or class name and do not bind window
to root
in the UMD / AMD wrapper that they use sometimes. In this case we host a modified version where we define window
as root
.
Using require with the ES6 module structure can introduce problems and needs a different babel config.
Closing as we did not receive any further updates regarding this issue. If there are still issues please open a new issue.
I set up foundation with the cli template and wanted to include the jquery plugin fancybox. In previous versions without webpack, I would include the path to my fancybox bower plugin in
config.yml
.How does it work now with webpack?
Do I need to add it in
config.yml
?Or in my app.js like this?
really confused about how to include it and nothing works thus far. Have been trying different things. I am not too familiar with webpack, but I guess that is now a prerequisite for using foundation.
What is the best practise or at least, how can I make this work?