Webpack 2 accessible functions from different js files - javascript

Just started using webpack-2 and have a question about global functions. Have these functions in js file named showPictures.js:
function isEmpty(el) {
var result = !$.trim(el.html());
return result;
}
function showPicturesList() {
if (!isEmpty($('#picture-name-list'))) {
var pictureList = document.getElementById("added-pictures");
pictureList.style.visibility = 'visible';
}
}
And I have another file util.js in witch I am calling showPicturesList() function
window.onload = function(){
showPictureList();
}
Simply using js I would import both scripts into my html, but with webpack I can make one file for both of them so webpack.config.js I added both of these files as entry array.
My output file bundle.js looks as it should it has both of those files inside of it. The question is what would be the easiest way with minimal changes on js files to call showPictureList() function from utils.js file?

You can use ES2015/ES6 modules to import your functions which have been exported in another file. In your showPictures.js file you export the functions you want to expose, by adding the export keyword.
export function showPicturesList() {
if (!isEmpty($('#picture-name-list'))) {
var pictureList = document.getElementById("added-pictures");
pictureList.style.visibility = 'visible';
}
}
And then you need to import them in your util.js.
import { showPicturesList } from './showPictures';
For detailed informations on how to use modules you can have a look at Exploring JS: Modules.
With this you also don't need to add both files to entry in your webpack config, because webpack will see the imports and include eveything you're importing.

Related

Add functions in other folder, to an object in this folder

I want to create an object that would import functions from another folder and it would look something like this:
class = {
functions: {
//All functions here
}
}
The functions would be inside of a different folder, however, I want to make some sort of importer in which it would make new classes for each new function/file it finds inside of the folder.
someFunction.js Function File:
function someFunction() {
console.log("this is some function");
}
So I would like for something to look like this:
class.functions.someFunction()
No, I do not want to have it hard coded into the object, I want to import all functions from a folder and create functions like that.
Well, first I wan't to answer your question as I think you want, even if I also think it is not the correct way to proceed.
I'll also assume that with class you are not referring to an actual ES6 Class, but we are talking about a plain object.
So this is the code:
const fs = require('fs');
const path = require('path');
function importer(dirPath) {
const absoluteDirPath = path.normalize(
path.isAbsolute(dirPath)
? dirPath
: path.resolve(process.cwd(), dirPath)
);
const output = {
functions: {}
};
const content = fs.readdirSync(path.normalize(absoluteDirPath));
content.forEach((basename) => {
const absoluteItemPath = path.join(absoluteDirPath, basename);
if (fs.statSync(absoluteItemPath).isFile() && /\.js$/i.test(basename)) {
output.functions[basename.slice(-3)] = require(path.relative(
__dirname,
absoluteItemPath
));
}
});
return output;
}
module.exports = importer;
For this to work, all your functions in your files should be exported like:
module.exports = function myFunction() {};
To use the 'importer', you just do:
const artemis = importer('/path/to/directory'); // PATH MUST BE ABSOLUTE OR RELATIVE TO CWD.
/*
SUPPOSING THAT YOUR DIRECTORY CONTAINS THE FOLLOWING FILES:
function1.js
function2.js
Then you can do:
artemis.function1();
artemis.function2();
Please note that your files must be named in a JS friendly way (a valid string for an object key).
*/
A final important note about this odd method: This will only ever work in a NodeJS environment. Even if functions could have worked in other environments (like a browser). The next method, will work for any ECMAScript environment after proper building process: transpilation (EX: Babel) and bundling (EX: Webpack).
Suggested Solution
Use ES6 Static import / export like modern JS libraries do. This comes with huge benefits, from static code analysis to tree shaking and more.
Let's suppose the following hierarchy:
// - index.js
// - internals/
// - index.js
// - module-1.js
// - module-2.js
internals/module-1.js
function module1() {}
export {module1};
internals/module-2.js
import {module1} from 'module-1.js';
function module2() {
// YOU CAN USE module1 IF YOU NEED. (AVOID CIRCULAR REFERENCES)
module1();
}
export {module2};
internals/index.js
import {module1} from './module-1.js';
import {module2} from './module-2.js';
export {module1, module2};
index.js
import * as moduleGroup from './internals/index.js';
export {moduleGroup};
Finally, where you import your moduleGroup, you can do:
moduleGroup.module1();
moduleGroup.module2();
Obviously this is a basic scenario, but this is, IMHO, the correct way to deliver a group of functions and other stuff. Please let me know if you have any doubt.

Webpack global variable from multiple files

I'm trying to rewrite bunch of legacy JS files into module structure. I have obfuscated plugin which contains out of few files, which in turn work with single global variable. The order of execution of these files matters.
Example:
file1.js
var myModule = {someStuff};
file2.js
myModule.someProperty = someValue;
What i want to achieve is to import them all somehow and get this global variable myModule.
Possible implementation:
myModule.js
import myModule from "file1.js";
import myModule from "file2.js"; // ofc i know it does not work this way
export default class myProgramm {
constructor(){
myModule.run({options});
}
}
What i tried so far is webpack provide plugin (https://webpack.js.org/plugins/provide-plugin/), but it doesn't work with multiple files. Also i tried to use provide-multiple-plugin (adopted to webpack 4) from this gist :https://gist.github.com/shellscape/a7461022503f019598be93a512a1901a. But it seems to include files in nearly random order, so it can happen that myModule is not defined, while file2.js is executed first.

How does the JavaScript Import work under the hood?

How does the import statement actually work in JavaScript? I read the documentation and it says that it places exported code within the scope of the file. Does that mean that the code is copied over into the file where I type import?
For example - in library.js I have:
export {export function getUsefulContents(url, callback) {
getJSON(url, data => callback(JSON.parse(data)));
}
In main.js I have:
import { getUsefulContents} from 'library.js';
getUsefulContents('http://www.example.com',
data => { doSomethingUseful(data); });
This allows me to call getUsefulContents() in main.js. My question is, does main.js now have the contents that I exported from library.js?
Is using import the same as just having physically defined getUsefulContents() in main.js?
function getUsefulContents(url, callback) {
getJSON(url, data => callback(JSON.parse(data)));
}
getUsefulContents('http://www.example.com',
data => { doSomethingUseful(data); });
The main reason why I ask is because I want to know if using import will have an effect on main.js file size? Or is something else going on under the hood?
Thank you!
Depends on how you are using main.js. If you run it through a bundler, then the bundler will probably include library.js into main.js to pack it up into one file. In that case, the only advantage would be maintainability and ease of development because you are focused on the file you are working on. If you are simply running the import statement and deploying your application, the import statement won't affect the file size of main.js.
It just namespacing it within the file that you are importing it to so
any code from useful-library.js is included in the file, I visualize it this way
import { usefulCodeFromLibrary } from './useful-library.js';
((usefulCodeFromLibrary)=>{
// My excellent code
// Imported code doing it's job
usefulCodeFromLibrary.someHelperFunction()
}()

ES6 import syntax imports whole file instead of function only

I have a couple of JS files with quite a few functions. In one of the files, I have a function written that I wish to export and use in another file. Here is the function:
export default function updateMinimumAmountNotice(subtotal) {
let parsedSubtotal = parseFloat(subtotal);
let minimumOrderAmount = parseFloat(minimum_order_amount);
if (parsedSubtotal < minimumOrderAmount) {
minimumOrderNotice.find('#checkout-amount').text((minimumOrderAmount - parsedSubtotal).toFixed(2));
} else if (parsedSubtotal >= minimumOrderAmount) {
minimumOrderNotice.hide();
}
}
In my other file, I am importing it like so:
import updateMinimumAmountNotice from './single-product';
When I import the function updateMinimumAmountNotice, I get errors on the page that are from non-imported functions in the same file of the function that I am importing. None of those functions are exported and the file is not loaded on the page. Most of the JS files are page-specific and only load on the page they have logic for.
If it matters, I am using Webpack as a build tool with BrowserSync.
So, is this normal behavior for importing/exporting modules, or is there something else going on?

Automatically export everything from ES5 file to be used in ES6

I have pretty straightforward ES6 code (init.js):
import App from '../vendor/app';
window.init = function() {
let app = new App();
app.hello(); // prints "hello" to console
}
app module (app.js) is ES5 one and I don't want to modify this file:
function App() {
}
App.prototype.hello = function() {
console.log('hello from vendor module');
}
The code above won't work, because I need to add
export default App;
to the end of app.js. But I want to keep vendor files clean and without any modification as much as it possible. The tricky part is that app.js is depending on other ES5 modules, for example:
App.prototype.hello2 = function() {
dialog.show('hello from vendor app module, but using another vendor "dialog" module');
}
dialog variable is defined in ES5 dialog.js.
It works well when you add script-tags to your html page. I also want to avoid that. Ideally, I want to modify init.js only. Use some sort of import, so it will attach all of the vendor modules automatically to my init.js.

Categories

Resources