URL cache-busting parameters with RequireJS? - javascript

I'm using RequireJS (the jQuery version) and I want to append GET parameters to my scripts to prevent unwanted caching.
I'm using the urlArgs parameter, as suggested in the docs. This is my app-build.js file:
({
appDir: "../",
baseUrl: "scripts/",
urlArgs: "cache=v2",
...
Then I build the project as follows:
$ node ../../r.js -o app.build.js
The output in app-build directory now contains both require-jquery.js, which is the same file as previously, and require-jquery.js?cache=v2, which is blank.
The index.html file doesn't seem to have any references to cache=v2. And when I load the page in a browser, I don't see any cache=v2 parameters appended to any of the scripts.
Am I doing something wrong?

The docs on urlArgs:
“During development it can be useful to use this,
however be sure to remove it before deploying your code”
and this issue from Github, James Burke:
“do not try to use urlArgs during build”

The urlArgs parameter is more of a runtime configuration (i.e., only understood by RequireJS, not the r.js optimizer), seemingly due to its author's stated belief that it is only suited to development (and "bad" dev servers that don't send proper headers). So you'd either need to configure it in your require.config call (in a .js file loaded by require.js, typically main.js or config.js):
require.config({
// other config, like paths and shim
urlArgs: "cache=v2"
});
Or, per this other SO answer, you'd define it in directly in a <script> block before loading require.js.

I would try using a different build.js file for the optimizer vs the build.js file you use running the live app. Based on your description, the optimizer script doesn't seem to properly handle the urlArgs parameter (since it's outputting a file called require-jquery.js?cache=v2).
I wouldn't expect cache=v2 to show up in index.html (why would it?), but you're right to expect it in the network activity log.

Related

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.

How to use webshim with assetic in a Symfony2 project?

I would like to use Webshim in a Symfony2 project.
So far, the webshim library is in mybundle/Resources/public/components/webshim...
The webshim library has a polyfiller.js that loads specified scripts from the ./shims directory. This is also clearly explained from the webshim docs:
The code inside of the polyfiller.js automatically detects the path to the script it is run from and assumes, that the shims folder is in the same directory. This means, you have to make sure, that either the shims folder is placed parallel to the code of the polyfiller.js or to configure the path using the basePath option.
I'm using other libraries and they all end in the /web/js or /web/css directories as they should do. They are combined and have names like "6464de0.js" and are perfectly accessible.
But, webshim tries to load scripts from the shims folder. This makes sense when you look at the docs.
This is an example of 404's in the console:
GET http://domain.dev/app_dev.php/js/shims/combos/1.js 404 (Not Found)
How can I make the webshim library work with assetic?
I have the same issue and here is what I did:
Put the 'shims' folder in the public folder of your desired bundle (eg. AcmeBundle/Resources/public/js/shims) then when you do assets:install using the console command it will be installed in the Symfony/web directory.
Then set the webshim option so that it points to that path:
webshim.setOptions('basePath', '/bundles/acme/js/shims/');

How can i use the RequireJS optimizer to optimize my app to not use RequireJS anymore?

The Answer is below the question:
Maybe I don't understand the whole RequireJS thing fully,
but here is my problem:
I got a set of files like that:
sub
sub1.js
sub2.js
main.js
In all of the files in sub, i use the define() function to define modules. In the main.js, i use the require() function to load all modules. All of this works.
Now when i run the optimizer (r.js) on the main.js, it just takes the content of all files and puts it into one file. Yes, i can then use this optimized file to do the same as what i could do with the multiple files.
All good, no error.
Now my question: In that optimized file, it still uses RequireJS. Can i optimize it to the point, where it doesn't use RequireJS, where it's just the functions put together?
Answer
You can only include RequireJS into your optimized file by setting the include option to "requireLib".
Are you trying to load the file in the script tag w/o using data-main + require.js? OR, are you trying to render the file so that RequireJS is no longer used at all? I suspect it's the latter, which is not possible. If the former, that is achieved by bundling Require in via a build file option: http://youtu.be/m6VNhqKDM4E?t=12m44s
No you cant. The point of the r.js is to compile all your dependencies situated in multiple files into one. So even after compiling the modules are still AMD modules, but now without the need to load them separately. And the modules still need an AMD loader to get work. The only thing you can do after compiling is to use a more lightweight loader loader like Almond

RequireJS and a multilanguage website

(warning: I am a newbie with require.js)
I am using the RequireJS Optimizer to combine all require.js JS files into one file and I don't know why the output JS file contains only the root bundle.
My lang/nls/strings.js file is http://pastie.org/private/7o6fa7sfrxvppu4lcunz0a
And after running 'node r.js' there is no 'lang/nls/de/strings' declaration http://pastie.org/private/dyktxwv4wgdywbj8mltw , although I have a require/lang/nls/de/strings.js file
The build example of r.js https://github.com/jrburke/r.js/blob/master/build/example.build.js states that 'Only one locale can be inlined for a build' but I hope there is a way to include in the optimized file all the language strings that my app need. So how can I achieve this ?
As you read only one local can be inlined, which totally makes sense as you dont wanna load all locals, cause in most cases the user needs only one. RequireJS will automatically detect whats the browser local and load the missing locals if they exist. If you need all locals, dont use requireJS and inline them as plain JSON.

RequireJS and Mustache (or any other engine): where to put templates

I am using RequireJS and Mustache in a Javascript application. The content of the templates is inside some external files, which are loaded via the text plugin.
The only thing that slightly annoys me is the directory structure this imposes. All my scripts live inside a js directory, like this
index.html
js
libs
require.js
text.js
jquery.js
...
controllers
...
views
...
...
Hence I configure RequireJS with baseUrl = 'js', to simplify module names. But this force me to have templates inside the js directory, otherwise they are not visible to the text plugin.
Is there a way to configure RequireJS so that text files dependencies are looked elsewhere than the scripts directory?
(Of course I could avoid the text plugin and manually define AJAX requests to grab the files, but this is not the point of the question. If possible, I would like to use the existing tools)
You can specify an absolute path. From the docs:
However, if the dependency name has one of the following properties, it is treated as a regular file path, like something that was passed to a tag:
Ends in ".js"
Starts with a "/"
Contains an URL protocol, like "http:" or "https:"
I usually set up my baseUrl to . and script paths starting with js like this:
require.config({
baseUrl: ".",
paths: {
"lodash": "js/ext/lodash/dist/lodash",
"jquery": "js/ext/jquery/jquery",
"domReady": "js/ext/requirejs-domready/domReady",
"text": "js/ext/requirejs-text/text.js"
}
});
Now I can keep templates in ./templates and reference them easily.

Categories

Resources