Including bundled webpack file in webpack build - javascript

I have a webpack bundled widget that I pack into a single file using webpack, and can use as follows:
<script type="text/javascript" src="my-bundle.js"></script>
<script type="text/javascript">
(function() {
MyBundle.render();
}) ();
</script>
This works fine, but I want to use this widget in my main Rails app. So I've copied the my-bundle.js file into my main project directory and required it.
When I run webpack on my main app, I can see that the code in my-bundle is being included in the resulting js file, but I cannot access the code. i.e. calling MyBundle gives a not defined error.
How can I access it?
EDIT - it looks like I can just use script-loader to run the my-bundle.js file once (which defines a MyBundle function). This doesn't feel like the best way to do it though

Related

Old AngularJS project migration to bundled js + minification with browserify

I have a very old AngularJS project which is quite big. Instead of creating a bundled .js file composed of all the required code, this project is organized in the following way:
All the .js files are directly loaded in index.html with a <script src="path/to/js">
Even the dependencies minified .js files are loaded in the same way, examples:
<script src="bower_components/angular-route/angular-route.min.js"></script>
<script src="bower_components/angular-resource/angular-resource.min.js"></script>
<script src="bower_components/angular-cookies/angular-cookies.min.js"></script>
The code makes vast use of definitions (functions, classes, enums and so on) declared in different .js files without importing them (because they are all available globally). Examples:
// inside one file, PastFuture is not declared here
if (self.pastFuture === PastFuture.FUTURE) {
... // do something
}
// inside another file, it is not exported or anything, it is just defined
const PastFuture = {
PAST: 'PAST',
FUTURE: 'FUTURE'
};
I want to migrate this project into something a bit more "standard". I've removed bower for npm dependencies but now I'm stuck at forcing all these .js files to get bundled together.
The major problem of the code is that once bundled with browserify, all the definitions not imported stops working, for example, PastFuture is not defined unless I import it manually wherever is required.
Is there a way to overcame / solve this problem without adding exports and require in all the files of the project?
I was thinking that if I concatenate all those .js files instead of trying to make them require each other, it would have the safe effect without the need to add exports and imports.. but as a solution, it just sounds like a hack to me and I was searching for something more correct.

Angular - How to import a module from a JS bundle

I am trying to import a module from a generated Angular library bundle located inside a vendor subfolder under src/.
index.html
<head>
...
<script type="text/javascript" charset="utf-8" src="./vendor/example/bundles/example.umd.js"></script>
</head>
Nevertheless, I am having some troubles importing module from this in my app.module.ts. Please, any idea of how to do it?
It seems that #angular/core and #angular/common peerDependencies of angular library should also be bundled inside script to work correctly.
I will appreciate any kind of help
You shouldn't add a <script> tag that refers to a local file because this local file won't be included in the build.
Instead, use the scripts configuration section of the angular.json file, like this:
"scripts": [
{ "input": "src/vendor/example/bundles/example.umd.js" }
]
This will embed the example.umd.js file inside a dedicated file of the Angular's build. As it's packaged as UMD, an object will be attached to window which contains the API of the library you are importing.
In order to stop TypeScript for complaining about a non-existent variable, just add this: declare var example; (replace example with the real name of the global object).

Import non-module vendor script in webpack

I'm building an app with the AirConsole JS service. AirConsole only provides their library as a .js file you would include in your page with the usual:
<script type="text/javascript" src="https://www.airconsole.com/api/airconsole-1.6.0.js"></script>
However, I'm using Webpack and would like to import the script into my other JS files. I have tried a few methods with no luck:
Create an entry file named vendor which imports the airconsole.js file. This creates a vendor.bundle.js file which I can include on my page
Add the AirConsole path to my index entry point so the script is included in the bundle.js file. With this method I can verify the AirConsole code is included in the bundle.js file but attempting to create a new instance of AirConsole results in AirConsole is undefined
Am I on the right track with these methods? If not, what is the recommended way to import a non-module .js file?
The best way is by an action which we call "shimming". You can check out our new docs page for information. There are a few different ways to do on it (that depend on the needs) for your non-module.
https://webpack.js.org/guides/shimming/

Browserify modules cannot be referenced from index.html after including bundle.js script

I'm using Browserify to access a Node module from an index.html file (hosted on Google App Engine)
I import the module in a "main.js" file, as I see is the standard in the Browserify documentation, as follows:
var request = require('request');
var fs = require('fs');
I then bundle this up into a bundle.js file using the following command:
browserify main.js -o bundle.js
This successfully produces the required bundle.js file. I then include this at the top of the header in my index.html as follows:
<HEAD>
<script src="/scripts/bundle.js"></script>
<script src="/scripts/util/loader.js"></script>
<!-- More scripts below here -->
A script within the body of index.html then makes a call to a function within loader.js which uses the line
request('api.my-url.com/world').pipe(fs.createWriteStream('/resources/myMap.json'));
Which I use to attempt to create a file containing the contents of the response. However, when I deploy this on GAE, and access index.html, I am greeted by the error message:
loader.js:15 Uncaught ReferenceError: request is not defined
at loadWorld (loader.js:15)
at Object.create ((index):55)
If I try and move the request() call up into the script in index.html I get the same problem, but if I move the line into main.js, I no longer get this issue.
I assume this is down to a personal misunderstanding of Javascript, but I can't seem to figure out why the request object is not available in index.html after bundle.js has been included in index.html via a script tag.
Many thanks to anyone who can shed some light on the situation, thanks.
When you create a browserify bundle, it is intended to be the application's "entry-point". But it seems that here you have your entry-point in index.html, so what you want is to bundle a standalone library.
Browserify has an option called --standalone to do this, which generates a UMD bundle instead: https://github.com/substack/browserify-handbook#standalone
You invoke it in much the same way, but specify what name (in the global namespace) the UMD bundle should be given. Eg.
browserify foo.js --standalone mylib > bundle.js
Now when you include <script src="bundle.js"></script> in your html, subsequent scripts will have be able to reference the mylib object.
Here's an example of using the --standalone option:
https://github.com/joshwnj/react-visibility-sensor/tree/master/example-umd
https://github.com/joshwnj/react-visibility-sensor/blob/master/package.json#L9
Also, if you want something like request that can be used in the browser, https://www.npmjs.com/package/xhr has a very similar API.

how to use webpack to load CDN or external vendor javascript lib in js file, not in html file

I am using react starter kit for client side programming. It uses react and webpack. No index.html or any html to edit, all js files. My question is if I want to load a vendor js lib from cloud, how to do I do that?
It would be easy to do that in a html file. <script src="https://forio.com/tools/js-libs/1.5.0/epicenter.min.js"></script>
However, in js file, it only uses npm installed packages. How can I import the above lib with no html file? I tried import and require, they only work for local files.
update 10/21/15
So far I tried two directions, neither is ideal.
#minheq yes there is a html file sort of for react start kit. It is html.js under src/components/Html. I can put cloud lib and all its dependencies there like this:
<div id="app" dangerouslySetInnerHTML={{__html: this.props.body}} />
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.4/jquery.min.js"></script>
<script src="https://forio.com/tools/js-libs/1.5.0/epicenter.min.js"></script>
<script src="/app.js"></script>
<script dangerouslySetInnerHTML={this.trackingCode()} />
</body>
Good news is it works, I don't need do anything else in js file, no import or require. However, now I have two jquery libs loaded in different ways. One in here, the other through npm and webpack. I wonder it will give me trouble later. The react-routing I use give me 'undefined variable' error if I type a none home path in browser window due to the server side loading I guess. So this solution is not very good.
Use webpack externals feature. This is documented as: link. "You can use the externals options for applications too, when you want to import an existing API into the bundle. I.e. you want to use jquery from CDN (separate tag) and still want to require("jquery") in your bundle. Just specify it as external: { externals: { jquery: "jQuery" } }."
However, the documentation I found a few places are all fussy about how to do this exactly. So far I have no idea how to use it to replace <script src="https://forio.com/tools/js-libs/1.5.0/epicenter.min.js"></script> in html.
externals is not intended to let you do this. It means "don't compile this resource into the final bundle because I will include it myself"
What you need is a script loader implementation such as script.js. I also wrote a simple app to compare different script loader implementations: link.
var $script = require("scriptjs");
$script("//ajax.googleapis.com/ajax/libs/jquery/2.0.0/jquery.min.js", function() {
$('body').html('It works!')
});
You can create a script tag in your JS as
$("body").append($("<script src="https://forio.com/tools/js-libs/1.5.0/epicenter.min.js"></script>"))
There is one html file that is definitely being used to serve to users with your js bundle attached. Probably you could attach the script tag into that html file
Use webpack's externals:
externals allows you to specify dependencies for your library that are
not resolved by webpack, but become dependencies of the output. This
means they are imported from the environment during runtime.
I have looked around for a solution and most of all proposals were based on externals, which is not valid in my case.
In this other post, I have posted my solution: https://stackoverflow.com/a/62603539/8650621
In other words, I finished using a separate JS file which is responsible for downloading the desired file into a local directory. Then WebPack scans this directory and bundles the downloaded files together with the application.

Categories

Resources