Can not include JQuery without npm in Vue JS project - javascript

I'm trying to import JQuery without using npm to my Vue JS project. Here's what I'm trying:
***jquery-functions.js***
import '../../public/js/jquery.min.js'
export function bar(){ $(".foo"){...} }
/$ is not defined as function/

var hello is evaluated in module scope, this prevents variables from leaking to global scope.
In order for a global to be defined, it should be assigned explicitly as such:
window.hello = function (x){x+5};
As for jQuery, it's specific to how the module works. It's UMD module and it isn't exposed as a global when jquery.min.js is imported as a module.
It should be assigned explicitly as a global either:
import jQuery from '../../public/js/jquery.min.js';
window.$ = window.jQuery = jQuery;
Or this can be done by means of Webpack that is used by Vue CLI internally, as the answer in related question suggests.

I tried everything above but somehow I couldn't get it working. Either eslint was giving function not defined error for $() or bootstrap couldn't see the included jQuery. I don't know if it's ok to include jQuery globally but I found the solution by including jQuery to my index.html file with <script> tags. Then in my jquery-functions.js file I disabled eslint then everything was working just fine on run time.
***jquery-functions.js***
/* eslint-disable */
export function bar(){ $(".foo"){...} }
I did it like that so that I can separate jQuery methods from from Vue JS methods. It might be better to use npm to avoid including jQuery globally so that you can include it only in components that you need. For me I was concerned with compatibility of all other (6 of them) jQuery dependent libraries included in the template that I downloaded from internet.

Related

Should I use import jQuery in a script if jQuery is being added manually?

I am maintaining an existing project, and I saw this:
The site is already including jQuery the traditional way (it's WordPress, and WordPress includes jQuery by default unless you change stuff).
<script src="cdn-or-local/jquery.js"></script>
And then the site is including another javascript file, which has been compiled with Webpack and Babel.
<script src="wordpress-theme/dist/whatever.js"></script>
On the original whatever.js file (not the compiled one, but the human-created one), it states:
import $ from 'jquery';
$(document).ready(() => {
...
}
And this confused me a lot.
As far as I know, if jQuery is already being loaded before the whatever.js file is loaded, then $ will already be defined.
Question: can I just safely omit import $ from 'jquery';?
Yes, it's a good practice to import jQuery if your module needs jQuery - explicit declarations are good for readability, and will allow tooling to know what $ refers to! However, you can (should) configure webpack to not bundle jQuery as a dependency, but assume it is already loaded and available from a global variable.

How to access a variable from another JS file in webpack

I'm trying to implement webpack in a project, but can't seem to find a clear answer to this issue in their docs. I need to be able to access a certain variable globally from a JS file, for example:
toProps.js:
var myProp = "test";
In my entry point I do the following:
entry.js:
require('./toProps.js');
console.log(myProp);
But the variable myProp is undefined. This is an extremely simplified example, not my actual use case, but the point is that I'm working with an existing code base where there are these types of global references all over the place, but I want to implement some module and lazy loading with webpack.
How can I access the myProp variable?
Inside toProps.js:
var myProp = "test";
export default myProp;
Inside entry.js:
import myProp from './toProps.js';
From what I see, you haven't exported the variable. Therefore, it can't be an 'import' inside entry.js.
Edit 1: Learn more about exporting here.
Edit 2:
Okay, to make it a global variable, here's what I did:
Move props.js into /dist and link it inside index.html, before bundle.js, or whatever you've named the output file.
Now it's a global variable, so you don't actually need to export or import it anywhere.
To test this, I made a file called test.js, imported it into entry.js. Inside test.js is:
const logTest = () => {
console.log(myProp)
}
export default logTest;
Now inside entry.js, I invoked the function. It worked as expected and 'test' showed up in the console.
As you mentioned, your example is simplified, so this may not be viable for you. Maybe, you could move all the global variables to one file inside /dist, inside an object, as it's best not to pollute the global object.
Edit 3: Go with the answer from Jonas W. Totally forgot you could do that.
If you really need a global variable (no you dont!), use window:
window.myProp = "test";
Otherwise just export it from your file and import it everywhere you need it. That maybe adds some overhead to your code, but actually you always know where the value comes from, which makes debugging super simple.
Using webpack 4
To update this post for anyone that can read it, acctually you can use a plugin in webpack.config.js to resolve names that used in another .js files.
Take a look in https://webpack.js.org/plugins/provide-plugin/ example:
Usage: jQuery
To automatically load jquery we can simply point both variables it exposes to the corresponding node module:
new webpack.ProvidePlugin({
$: 'jquery',
jQuery: 'jquery'
});
Then in any of our source code:
// in a module
$('#item'); // <= just works
jQuery('#item'); // <= just works
// $ is automatically set to the exports of module "jquery"
If the source file to import belongs to maintainer, it's best to export first and import latter. Just like the answer of #Ibrahim.
I also encounter a situation to import third party source file just not using export syntax. So I think below is a solution while using webpack.
First, install exports-loader for your project.
npm install exports-loader --save-dev
Then, in your JS source file, import and use like below:
const WEBGL = require("exports-loader?WEBGL!three/examples/js/WebGL.js");
WEBGL.isWebGL2Available()
In my case, WEBGL is the inner variable I wish to import, three/examples/js/WebGL.js is the third party source file.
Hoping this is useful.

"Import a global variable" in Webpack [duplicate]

This question already has answers here:
Exclude react from webpack bundle
(3 answers)
Closed 5 years ago.
We have a webpack application that we're integrating into a site that uses traditional JS scripts, and those scripts define global variables.
Inside our webpack application, we want to import some libraries that happen to already be on the page as scripts. Rather than download the same code twice, once as a script and again embedded inside the webpack bundle, we'd like webpack to not include the code for the library already on the page as a script, but still allow us to use the ES import syntax to "import" the code in our modules, even though the script code in question actually made the library available by a global variable.
So, we have <script src="jquery.js"> on our page. jquery.js supposedly does something like this:
window.jQuery = {};
And in our code compiled by Webpack, we'd like to do:
import jQuery from 'jquery';
jQuery === window.jQuery // true
Is there any way for Webpack to be configured to resolve certain dependencies, like "jquery" in the above example, and determine that it should transform the import code into a reference to that global variable?
The intent here is to gradually opt into the new ES module syntax in new code in our legacy application, while still taking advantage of the fact that the same code is already available on the page as a script.
I checked Webpack's guide on "shimming" but it seems to offer every capability except the one I've described in this post.
Use webpack's externals:
Prevent bundling of certain imported packages and instead retrieve
these external dependencies at runtime.
externals: {
jquery: 'jQuery'
}

Importing an old ES5 module for use in a ReactJS component

I'm trying to use an ES5 module in a new ReactJS application and I'm struggling to understand how to correctly import that module, such that the main function within it can be found and executed.
I'm loading the module;
import 'air-datepicker';
I know I'm doing something wrong here and that it's not as simple as this, for an old library that doesn't have proper exports!
Anyway, then I should be able to manually initialise a date picker using an existing div like this;
$('#myDiv').datepicker();
I've tried multiple variations of the import and require, but I'm always getting the same error - 'datepicker is not a function'.
The library I'm experimenting with is air-datepicker. I've installed the module using npm without problems and I know the library works perfectly without React on a simple page loading the script manually in a script tag. My ReactJS app is a basic template created using 'create-react-app', from the FB tutorial pages.
If you're using create-react-app, you should be able to import it like
import 'air-datepicker/dist/css/datepicker.min.css';
import 'air-datepicker';
If you added your jQuery using <script> tag in your HTML, you need to add this line before the air-datepicker imports
const $ = window.jQuery;
const jQuery = window.jQuery;
If you added jQuery using npm install, you'll have to add these following lines
import $ from 'jquery';
import jQuery from 'jquery';
window.$ = $;
window.jQuery = jQuery;
//... air-datepicker imports
Make sure to initialize it inside your componentDidMount or somewhere you're sure that the element has been mounted already.
componentDidMount() {
$('#my-element').datepicker();
}
render() {
return <div>
<input
id="my-element"
type='text'
className="datepicker-here"
data-position="right top" />
</div>
}
Well, that's a day of my life that I'm never getting back!
The problem was caused by Babel import ordering. Import statements are hoisted - meaning they are evaluated first, before any other code (i.e. my window. assignments) are executed. This is 'by design' in babel.
The only way to avoid Babel hoisting, from what I can tell, is to avoid 'import' altogether and use require instead.
So, in the following order the global $ will have been set when you come to require air-datepicker. If you try to 'import' air-datepicker it won't work because Babel will evaluate all of your import statements before executing the window. assignment.
import $ from 'jquery';
window.$ = $;
require('air-datepicker');
There are one or two other approaches that also would have worked, but they are all less desirable because they need you to manually configure webpack - i.e. 'ejecting' the create-react-app config and going it alone...
Use the imports-loader;
// only works if you disable no-webpack-loader-syntax
require("imports?$=jquery!air-datepicker");
or, use the ProvidePlugin, making the module available for all modules.
You have to give it an identifier:
import datepicker from 'air-datepicker';

Use Browserify with JavaScript libraries such as Backbone or Underscore?

I know I can install underscore using npm but that's not what I can do in my work environment. I need to be able to download the Underscore.js library and then make it "browserify-compatible".
So let's assume Underscore.js looks something like this:
(function() {
var root = this;
// Rest of the code
}.call(this));
I downloaded that file on my hard drive and saved it as under.js.
My file that requires underscore looks like this:
var underscore = require("./under");
console.log(underscore);
And then I run browserify from the cli.
I have an HTML page called test.html and basically all it does is load the generated bundle.js.
However, the console.log(underscore) line fails - says that underscore is undefined.
What have I tried?
Obviously I added module.exports to the first line - right before the function definition in under.js, and that's how I got the error mentioned above. I also tried the method from this answer , still got the same error.
So, how would I use Browserify to load libraries such as Underscore.js or Backbone without using npm-installed modules?
That's because browserify does not add variables to the global scope. The version you download is identical to the version that you install via NPM.
You need to explicitly attach it to the window to export it to the top level scope.
If you create a file called "expose_underscore.js" and put this in it:
var _ = require('./under');
window._ = _;
Will do it, followed by: browserify expose_underscore.js > bundle.js and then add bundle.js as a <script> tag you will be able to do the following in your console:
HOWEVER, you shouldn't do this if you're using browserify. The point behind it (and Node's version of commonJS) is that you explicitly require it everywhere you need it. So every file you have that needs underscore should import it to a local variable.
Don't worry -- you will still only have one copy loaded.
I typically add my vendor libs like Underscore as script tags. Underscore will attach itself to the global scope, so then you don't need to require it anywhere to use it.
If you do want to use it in a Browserified fashion, verify that you have the correct path in your require statement (browserify requires are relative paths) and move the module.exports statement to the end of the file.

Categories

Resources