Closed medihack closed 7 years ago
The same obviously happens when adding foundation.min.js
or foundation.js
. Have you found a workaround?
ERROR in ./~/foundation-sites/dist/foundation.js
Module not found: Error: Cannot resolve module 'foundation' in
/home/kirsebaer/testproject/node_modules/foundation-sites/dist
@ ./~/foundation-sites/dist/foundation.js 2045:4-2047:6 3747:4-3749:6 3932:4-3934:6 4145:4-4147:6 5619:4-5621:6 7027:4-7029:6
+1
You guys have done so much nice work in allowing us to modularly import SCSS, it's a tragedy that I can't use this library because your javascript is essentially un-importable as a CommonJS module. This is going to severely limit its adoption in both webpack and browserify build environments.
+1
+1
+1 For now this is the biggest problem for me and the reason why I can't completely switch to foundation. Can't imagine why JS modularity is so bad, while SASS modularity is so good... Would love to see ES2015 modules support, but any other webpack compatible modules support will do the job.
Seeing the same problem. Having to use Bower to work-around it so far.
Added a StackOverflow question: http://stackoverflow.com/questions/34297788/npm-zurb-foundation-webpack-cannot-resolve-module-foundation
@MTyson I posted my temporary workaround on your StackOverflow entry. Enjoy
+1 @Nerdinacan Thanks, you put me on the right track! I've posted my workaround on the StackOverflow question adding some steps and explanation, hope you don't mind.
+1
+1
My solution using a single js file (no need a app.js and vendor.js): http://stackoverflow.com/a/34611081/4794469
+1 here... it took me a while to find this post. i took on one of the workarounds posted above. Anyone have any ideas what is the problem with the current JS base? As I can see the module definitions are there, but webpack seems to have a problem with the 'foundation' dependency.
(p.s. I'm a babel/webpack/commonjs noob so be nice if I'm talking silly here)
+1
I've noticed on the SCSS side switching from v5.x to v6.x there were compiling issues; the root file (foundation.scss
) didn't automatically pull dependencies. Did webpack work with v5?
Actually, yeah, I rolled back to v5 and things are working. I had to expose jQuery and $ as globals, but that was the only kludge. I just did:
$ = jQuery = require('jquery');
At the head of my entry file.
+1
+1
@tomByrer
that's an other story. you can just delete the mixin around the import and you`re good to go... or just use the mixin in your style.scss
UPDATED: feb 29 2016
A simpler solution (no vendor.js, no externals, simply an alias). 1 - Use this in your webpack config:
// this will force the export of the jQuery 'foundation' function, which we'll use later
loaders: [
{
test: /(foundation\.core)/,
loader: 'exports?foundation=jQuery.fn.foundation'
},
],
// this makes sure that every module can resolve define(['foundation']) calls
resolve: {
extensions: ['', '.js'],
alias: {
foundation: 'foundation-sites/js/foundation.core'
}
},
// this makes sure 'jQuery' is available to any jQuery plugin you might want to load
// (including Foundation files) regardless of how they are written
plugins: [
new webpack.ProvidePlugin({
$: 'jquery',
jQuery: 'jquery',
'window.jQuery': 'jquery'
})
]
2 - In your index.js:
// thanks to the ProvidePlugin we don't need to
// > import $ from 'jquery';
// import core foundation files
import { foundation } from 'foundation-sites/js/foundation.core';
import 'foundation-sites/js/foundation.util.mediaQuery';
/* import here any additional module */
// we need to attach the function we exported above to the jQuery object in use in this file
$.fn.foundation = foundation;
// ready to go
$(document).ready(function() {
$(document).foundation();
…
});
Thanks for the nice solution @mjsarfatti! :+1:
Got it working after installing babel-loader
and exports-loader
. I also had to quote the $
key in the ProvidePlugin
options object to get it working.
But a single module is still complaining about jQuery missing:
import 'foundation-sites/js/foundation.util.triggers'
The bundle contents look like webpack does not inject jQuery here. Do you know how to solve this problem?
Hey guys, it's much easier than you think ;)
Just npm i script-loader
and prefix the import with a script!
everywhere where you need to load the script in the global scope. No need to configure externals, aliases or ProvidePlugins in webpack.
If you want to load everything from foundation it would look like this:
import 'script!jquery'
import 'script!what-input'
import 'script!foundation-sites'
You can checkout my boilerplate project https://github.com/timaschew/r3-foundation-boilerplate
@tomByrer
I've noticed on the SCSS side switching from v5.x to v6.x there were compiling issues; the root file
Didn't see any errors. It's working fine with v6 in my boilerplate project.
@keimlink can you try modifying the loaders > test as such:
test: /foundation\.(core|utils)/
(or even simply test: /foundation/
)
@timaschew great, even better! My solution can actually cause problems when you attach foundation plugins to elements via data- attributes instead of with pure javascript, yours could solve that.
where and how does one declare $(document).foundation();
?
inside an angular2 app
I guess you would still declare it inside the $(document).ready(function() { ... }) call
I'm going with @timaschew's solution for now, seems to be working.
@medihack so is this solved for you, can this issue be closed?
@timaschew This thread is just a collection of different workarounds/hacks to circumvent the initial problem. IMO @Nerdinacan described it in the best way:
it's a tragedy that I can't use this library because your javascript is essentially un-importable as a CommonJS module
So my expectation is that the zurb people will come up with a fix or explain what should be fixed so that someone else can do it.
@mjsarfatti Thanks for the update! Will try it ASAP and post feedback here!
This thread is just a collection of different workarounds/hacks
@keimlink It's a decision of the authors which module types they want to support and maintain.
Of course they could provide to bundle foundation with the UMD format. But this doesn't make sense in combination with modular components (tabs, accordion, magellan), because every file would be exist additionally in the generated UMD format.
It would only make sense for the file (in the dist directory) which contains all the components. But in that case there is no support for picking/selecting particular components but this is what CommonJS should be, so this case doesn't make sense as well.
If there is a library, which is only available in one module type, in this case: using the global window scope - doesn't fit in your build pipeline, you need to use an adapter.
Every good bundler provides adapters: browserify and webpack and for webpack it's the script-loader it does exactly this job.
This thread is just a collection of different workarounds/hacks
So these solutions of browserify and webpack are no hacks, they are adapters.
@timaschew I disagree, it's a pity that in 2016 such a big project still hasn't adopted UMD. Every module should require the core and the core should require jquery. I'm not saying it's easy, it's very possible that adopting UMD would require a big rewrite and for this reason they haven't done it yet. But it has to be done or someone else will come forward (see lodash - which I can import function by function in my project - vs the monolithic underscore)
@mjsarfatti In your solution, why do you need to do : import $ from 'jquery';
in index.js
if you already declared jquery
in :
new webpack.ProvidePlugin({ $: 'jquery', jQuery: 'jquery' })
?
Can't you remove this import
line?
Good catch, in fact you most probably don't in this case.
I import it by default in all my projects (I don't always need the ProvidePlugin) and it became an automation I guess :) I haven't tested it but it should definitely work without that import.
@timaschew I finally tested your solution, and while it looked great I could not find a way to make it work when you import jQuery plugins written using the UMD alongside others written in the "legacy" way (in my specific case scrollToFixed and selectize).
At least when you define the script-loader in the webpack config: there might be a way if you specify which loader to use inline case by case, but I wanted a universal solution. The error I got was a "require is not defined", very weird.
@keimlink please disregard my previous reply :) I revised my code above, you just need to add 'window.jQuery': 'jquery'
to the ProvidePlugin
@mica16 you are most definitely right, I commented out that line and obviously it works.
Thanks for the update @mjsarfatti ! I will test it as soon as I have the time!
I haven't tried it so far, but it seems release 6.2 has converted everything to ES2015 which should also solve the import problem.
I'm very new to webpack and foundation. im trying to get foundation 6.2 work with webpack and npm. Can someone help me out here. in my webpack.config.js
module: {
loaders: [{
test: /(foundation\.core)/,
loader: 'exports?foundation=jQuery.fn.foundation'
}],
resolve: {
extensions: ['', '.js'],
modulesDirectories: ['node_modules'],
alias: {
foundation: 'foundation-sites/js/foundation.core'
}
},
},
plugins: debug ? [
new webpack.ProvidePlugin({
$: 'jquery',
jQuery: 'jquery',
'window.jQuery': 'jquery'
})
] :
then in my index.js my webpack entry file
require('!!script!jquery/dist/jquery.min.js');
require('!!script!foundation-sites/js/foundation.core.js');
require('!!script!foundation-sites/js/foundation.accordion.js');
require('!!script!foundation-sites/js/foundation.util.keyboard.js');
require('!!script!foundation-sites/js/foundation.util.motion.js');
$.fn.foundation = foundation;
// ready to go
$(document).ready(function() {
$(document).foundation();
});
but im getting index.js: Uncaught ReferenceError: foundation is not defined what im doing wrong here??
@fchengpc this is what I'm doing, based on what's been described in this thread (I'm on 6.1.x
though, not sure if it makes a difference):
import 'script!jquery'
import 'script!foundation-sites'
$(document).ready(function ($) {
$(document).foundation();
});
I'm not doing anything specific in the webpack file.
Try
var foundation = require('!!script!foundation-sites/js/foundation.core.js');
or possibly adding foundation to your provide plugin
new webpack.ProvidePlugin({
$: 'jquery',
jQuery: 'jquery',
'window.jQuery': 'jquery',
foundation: 'Foundation'
})
@anselmdk Thanks you. finally got it working now. You are right nothing special in webpack config.(i took most of stuff out). Here is what i have in entry file.
require('script!jquery');
foundation = require('foundation-sites/dist/foundation.min.js');
$(document).ready(function($) {
$(document).foundation();
});
not sure why i need to require jquery again. since i do use (webpack.ProvidePlugin) in webpack config. But if i took it out it throw jQuery undefined error. (assume b/c foundation use $, JQuery and window.jQuery
@priedthirdeye I actually end up use both. first ProvidePlugin in webpack config file then define foundation variable in entry file. Hope this help out someone the future.
@fchengpc that's cool. It could be that you're getting away with calling Foundation directly, because you're using 6.2
. I'll try that out when I upgrade.
I'm able to get Foundation 6 working with webpack if I use the scripts-loader via @timaschew's method. But I'm unable to specify the files I want explicitly. I have to include the entire JS library.
So, in short this works:
import 'script!jquery'
import 'script!what-input'
import 'script!foundation-sites';
but this doesn't:
import 'script!jquery'
import 'script!what-input'
import '!!script!foundation-sites/js/foundation.core.js';
import '!!script!foundation-sites/js/foundation.util.box.js';
import '!!script!foundation-sites/js/foundation.util.keyboard.js';
import '!!script!foundation-sites/js/foundation.util.mediaQuery.js';
import '!!script!foundation-sites/js/foundation.util.motion.js';
import '!!script!foundation-sites/js/foundation.util.timerAndImageLoader.js';
import '!!script!foundation-sites/js/foundation.util.touch.js';
import '!!script!foundation-sites/js/foundation.util.triggers.js';
import '!!script!foundation-sites/js/foundation.abide.js';
import '!!script!foundation-sites/js/foundation.accordion.js';
import '!!script!foundation-sites/js/foundation.accordionMenu.js';
import '!!script!foundation-sites/js/foundation.drilldown.js';
import '!!script!foundation-sites/js/foundation.dropdown.js';
import '!!script!foundation-sites/js/foundation.dropdownMenu.js';
import '!!script!foundation-sites/js/foundation.equalizer.js';
import '!!script!foundation-sites/js/foundation.interchange.js';
import '!!script!foundation-sites/js/foundation.magellan.js';
import '!!script!foundation-sites/js/foundation.offcanvas.js';
import '!!script!foundation-sites/js/foundation.orbit.js';
import '!!script!foundation-sites/js/foundation.responsiveMenu.js';
import '!!script!foundation-sites/js/foundation.responsiveToggle.js';
import '!!script!foundation-sites/js/foundation.reveal.js';
import '!!script!foundation-sites/js/foundation.slider.js';
import '!!script!foundation-sites/js/foundation.sticky.js';
import '!!script!foundation-sites/js/foundation.tabs.js';
import '!!script!foundation-sites/js/foundation.toggler.js';
import '!!script!foundation-sites/js/foundation.tooltip.js';
When including files specifically, the dropdownMenu doesn't work. It returns this error:
foundation.core.js:189 TypeError: Cannot read property 'Feather' of undefined
.
However, when importing individually there are other JS components that do work (orbit and interchange, for example).
does it help if you put the dropdown import to the end or change the order somehow?
@timaschew no, changing the order doesn't have any effect and still returns the same error: foundation.core.js:189 TypeError: Cannot read property 'Feather' of undefined(…)
This is how I currently do it using Foundation 6.2.1
var foundation = require("babel!foundation-sites/js/foundation.core"); require('babel!what-input/what-input.js'); require("babel!foundation-sites/js/foundation.util.mediaquery.js"); require("babel!foundation-sites/js/foundation.util.nest.js"); require("babel!foundation-sites/js/foundation.util.box.js"); require("babel!foundation-sites/js/foundation.util.keyboard.js"); require("babel!foundation-sites/js/foundation.util.motion.js"); require("babel!foundation-sites/js/foundation.util.timerandimageloader.js"); require("babel!foundation-sites/js/foundation.util.touch.js"); require("babel!foundation-sites/js/foundation.util.triggers.js"); require('babel!foundation-sites/js/foundation.offcanvas.js'); require('babel!foundation-sites/js/foundation.dropdownMenu.js'); require('babel!foundation-sites/js/foundation.dropdown.js'); require('babel!foundation-sites/js/foundation.equalizer.js');
// Related dependencies From package.json
"devDependencies": { "babel": "^6.5.2", "babel-core": "^6.6.0", "babel-loader": "^6.2.4", "babel-preset-es2015": "^6.6.0", "gulp-babel": "^6.1.2", [...]
I'm sure there's other ways to do it, but this is what works for me after many wasted hours trying to get it to work.
@priedthirdeye that is the best solution to be used with
new webpack.ProvidePlugin({
$: "jquery",
jQuery: "jquery",
"window.jQuery": "jquery"
})
Thanks for all the support here! Could we get this documented somewhere in the repo. Then I'd anyone comes and submits an issue or question on our (webpack) repo, we can link them to a solution.
@TheLarkInn @priedthirdeye @agualbbus We'd happily accept a PR to the docs adding this, perhaps on this page? (http://foundation.zurb.com/sites/docs/installation.html)
File found here: https://github.com/zurb/foundation-sites/blob/develop/docs/pages/installation.md
The problem I ran into specifically was Uncaught TypeError: $(...).foundation is not a function
, in other words, $.fn.foundation
wasn't being set. I tried every solution here and across the internet, and couldn't get anything to work.
I managed to get it working (after some code diving) by essentially pulling out the jQuery plugin code from ./js/foundation.core.js#253
and doing this:
// Foundation Sites Initialisation
// FIXME: Currently breaks, see: https://github.com/zurb/foundation-sites/issues/7386.
import 'what-input';
import 'foundation-sites';
$.fn.foundation = function(method) {
var type = typeof method,
meta = $('meta.foundation-mq'),
noJS = $('.no-js');
if(!meta.length){
$('<meta class="foundation-mq">').appendTo(document.head);
}
if(noJS.length){
noJS.removeClass('no-js');
}
if(type === 'undefined'){//needs to initialize the Foundation object, or an individual plugin.
Foundation.MediaQuery._init();
Foundation.reflow(this);
}else if(type === 'string'){//an individual method to invoke on a plugin or group of plugins
var args = Array.prototype.slice.call(arguments, 1);//collect all the arguments, if necessary
var plugClass = this.data('zfPlugin');//determine the class of plugin
if(plugClass !== undefined && plugClass[method] !== undefined){//make sure both the class and method exist
if(this.length === 1){//if there's only one, call it directly.
plugClass[method].apply(plugClass, args);
}else{
this.each(function(i, el){//otherwise loop through the jQuery collection and invoke the method on each
plugClass[method].apply($(el).data('zfPlugin'), args);
});
}
}else{//error for no class or no method
throw new ReferenceError("We're sorry, '" + method + "' is not an available method for " + (plugClass ? functionName(plugClass) : 'this element') + '.');
}
}else{//error for invalid argument type
throw new TypeError(`We're sorry, ${type} is not a valid parameter. You must use a string representing the method you wish to invoke.`);
}
return this;
};
$(document).foundation();
I should be able to do the same hack, sans the copy-pasting, if the jQuery plugin function is exported in the Foundation module for AMD. I suspect this would be kind of gross though, especially since it would require the user manually assigning $.fn.foundation
.
It looks as though @nueverest solved this in https://github.com/vuejs-templates/webpack/issues/254 with the config
externals: {
foundation: 'Foundation'
},
in webpack.conf
Can some of the other folks who are running into this check this solution out? If it works we'll add it to the docs
I would like to import some foundation js files in a webpack app.
In my entry js file I do the following:
The last one fails with the following error:
So it seems there is a problem with all files that contain the code
define(['foundation'] ...
asfoundation
is not defined anywhere.I installed
foundation-sites
(v6.0.5) using NPM.How do I import those files that have the
define(['foundation']
correctly?