I realize this might prove a total misunderstanding of what Webpack is for but I've not been able to find a straight answer anywhere.
Basically I have two files:
hello.js
function hello() {
console.log('Hello, world!');
}
entry.js
require('./hello.js');
hello(); // should log 'Hello, world!'
I wanted to pack them into a single file for faster loading using Webpack. My condition was that I should not have to modify hello.js in any way (let's say it is a big, obfuscated library that I don't have the right to modify).
I expected that running
webpack entry.js result.js
will give me a usable bundle in result.js but instead result.js gives me this error:
Uncaught ReferenceError: hello is not defined
Is there a way to achieve what I want? Just simply bundle scripts together to make them available in the global namespace without having to add anything to them ?
File hello.js is not exporting anything, you have to export hello function from hello.js file like this,
module.exports = function () {
console.log('Hello, world!');
}
and then in your entry file.
var hello = require('./hello.js');
hello();
Related
I'm doing a little testing setup for typescript. My main focus is to bundle all .ts modules into a single .js file that can be client-side referenced in a simple index.html. This is my test module:
// index.ts
import { Example } from './example'
class x {
example(): void {
console.log(Example)
}
}
let test = new x()
test.example()
// example.ts
export const Example : string = 'Example Message'
I compile everything into a bundle.js file using Webpack 5 and ts-loader. Then, I created an .html file to test the created class. There the test.example() inside index.ts (and then bundle.js) executed correctly, but the second one, inside the <script/> reports Uncaught ReferenceError: x is not defined.
<!-- index.html -->
<html>
<script src="../dist/js/bundle.js"></script>
<script>
// Uncaught ReferenceError: x is not defined
let test = new x()
test.example()
</script>
</html>
How can I reference my class x from the second <script/>?
How can I reference my class x from the second <script/>?
You can't. At least not without modifying your source code structure.
A bundler puts all your executable code into the bundle. That includes your dependencies, and your application code. And all that is only really designed to work from within that bundle via the import and export keywords.
The bundler manages those import/exports in a way that doesn't pollute the global scope. But it does require that you stay within that bundle.
However, you seem to want your bundle to make some values available in that global scope. And to do that, you must be explicit about it.
class x {
example(): void {
console.log(Example)
}
}
// Add `x` to the browser's global scope.
window.x = x
Now from some other <script> tag new x() should work as you expect.
I want to run several code before the code inside import syntax gets executed.
Example
file-1.js
console.log('Inside File 1')
import './file-2.js'
file-2.js
console.log('Inside File 2')
Output
Inside File 2
Inside File 1
The output I expected
Inside File 1
Inside File 2
Environment
Node JS v12.19.0 with Module configuration
Real Case
file-1.js
process.env.SHARED_DATA = 'Hello world'
import './file-2.js'
file-2.js
console.log(process.env.SHARED_DATA)
Output
undefined
You can define the env data in separate file. The import syntax will run in the order against the other imports as #loganfsmyth says.
Example
main.js
console.log('Inside main.js file')
import './set-env.js'
import './file.js'
set-env.js
console.log('Inside set-env.js file')
process.env.SHARED_DATA = 'Hello world'
file.js
console.log(process.env.SHARED_DATA)
Output
Inside set-env.js file
Hello world
Inside main.js file
The best way I find is to use top-level await with dynamic import.
process.env.SHARED_DATA = 'Hello world';
await import('../index.js');
In JavaScript the lines don't necesarily wait for the line before to end. One way to solve this issue of yours is to put the file-1.js into a async function:
async function f() {
process.env.SHARED_DATA = "Hello world";
return Promise.resolve(1);
}
f().then(() => {import "./file-2.js"});
By calling this function you can make sure the import waits for the f function to end! Then running the arrow function. Hope this helped if you want to read more about this topic here you go. https://javascript.info/async-await
We are trying a POC of adding Typescript and Webpack to our Angularjs project.
I am able to get my webpack bundle to generate, however at runtime the program cannot find the various functions in my validator.js. Can you please offer some advice?
login-view.components.ts
declare var findFormNode: any; //function in validator.js
//LogInUser
self.login = function ($event, command) {
if (findFormNode($event.target.id)) {
...
}
}
main.ts is importing the file
import "./../../../CommonStaticFiles/include/js/Validators.js";
bundle.js
eval("/* WEBPACK VAR INJECTION */(function($) {/*\r\n\r\n VALIDATORS\r\n\r\n ... n\n\nfunction findFormNode(
error
ReferenceError: findFormNode is not defined
at LoginController.self.login (login-view.component.ts:28)
at fn (eval at compile (angular.js:NaN), <anonymous>:4:267)
at callback (angular.js:29019)
In order for your functions to be properly imported, there are few things that you have to make sure of.
First, make sure you are exporting your functions correctly. Here's an example of how to export a function from Validator.js:
export const validateFunc1 = ():void => {};
Next, you have to make sure you are using proper import syntax. In order to import the function above, you would do the following:
import {validateFunc1} from "./../../../CommonStaticFiles/include/js/Validators.js";
Alternatively, if you want to import all exported functions at once, then you can use this syntax:
import * as validatorFuncs from "./../../../CommonStaticFiles/include/js/Validators.js";
Lastly, check that the location of Validators.js is correct. It's a common mistake to be looking in the wrong directory. Your code editor can usually help you find the right path to use.
I have created a number of String.prototype functions which for maintainability I'd like to have in its own file. That is, I'd like to include the file in a javascript project and thus have all the String functions defined.
I could create a module that exports each function, but then I'd have to assign each function as its own String prototype, yes? Something like
var myStringFunctions = require("myStringFunctions");
String.prototype.func1 = myStringFunctions.func1;
Is there a way to include such a file so that the prototypes are defined as part of the inclusion?
Try it, you will see your code and using require("./myStringFunctions"); works just fine.
./myStringFunctions.js
String.prototype.func1 = function() {
return this.toUpperCase(this);
};
./index.js
require("./myStringFunctions");
console.log("foo".func1()); // FOO
If your JS is going to run in the browser, you can use JS modules with the import and export syntax if you use a module bundling build tool like Webpack: https://webpack.js.org/ .
If your JS is running in a Node.js environment, modules are supported: https://www.w3schools.com/nodejs/nodejs_modules.asp
I am including my js file into my main html file like so
<script type="text/babel" src="js/scripts.js"></script>
Then I call one of my functions like so
<div class="allButton" id="completeAll" onclick="showAll('completeColumn');">Show All (...)</div>
the function looks like this
function showAll(column) {
$('div[id^='+column+']').removeClass('hide');
};
When I click the button(div) I get this error
Uncaught ReferenceError: showAll is not defined
I am using the text/babel as my script type because the file contains React JS stuff.
I have no idea why I simply cannot call my function. I am extremely new to ReactJS and Babel. (note: I am not using npm/gulp due to limitations)
Any help and/or advice would be appreciated
If you just define your function as follows you will be able to call it within the HTML.
window.showAll = function showAll(column) {
// your code here...
};
You have not exported your showAll function. When you transpile a JS/JSX file with Babel and bundle it to a scripts.js file (using Browserify or similar utilities), you must make sure to export your module (which tells your bundler to package it into your bundled file).
Your code should look like this:
var showAll = function(column) {
$('div[id^='+column+']').removeClass('hide');
};
module.exports = showAll;
This tells your bundler that your showAll method needs to be exported and available to other referenced namespaces.