requirejs HTML structure - requirejs

I know we could use requirejs combine files into one js file.
such like the following config.
module.exports = {
baseUrl: 'js/',
mainConfigFile: 'src/js/common.js',
dir: 'scripts/',
optimize: 'uglify2',
modules: [
{
name: 'common',
include: [
'jquery',
]
}
]
};
my result into one file is
common.js
----------------
jquery.js
modernizr.js
common.js
my question is, do we still need to put a require.js file in scripts folder and to use the following format
<script data-main="scripts/common" src="scripts/require.js"></script>
or we could just use
<script src="scripts/common.js"></script>
as files are compressed into one file?

You still need to load require.js the usual way to actually make use of the module loading benefits that it provides, and especially if you use the asynchronous functionality a lot. However, you can have a look at almond providing your code uses AMD and (from the README):
optimize all the modules into one file -- no dynamic code loading.
all modules have IDs and dependency arrays in their define() calls -- the RequireJS optimizer will take care of this for you.
only have one requirejs.config() or require.config() call.
do not use RequireJS multiversion support/contexts.
do not use require.toUrl() or require.nameToUrl().
do not use packages/packagePaths config. If you need to
use packages that have a main property,
volo can create an adapter module so
that it can work without this config. Use the amdify add command to
add the dependency to your project.
Almond is great because it doesn't need require.js at all; it wraps your own code with itself, which is a very minimal AMD loader skeleton and nowhere near as powerful as the main library. You then get a single optimised file that can be linked directly in your HTML:
<script src="scripts/common.js"></script>
The Gruntfile config for almond could look something like this:
compile: {
options: {
name: 'path/to/almond',
baseUrl: 'js',
include: ['main'],
insertRequire: ['main'],
mainConfigFile: 'scripts/config.js',
out: 'scripts/main.js',
optimizeAllPluginResources: true,
wrap: true
}
}
The above is all standard r.js boilerplate, you can find many more examples at the almond homepage.

Related

Compile Scss with Webpack

I'm still trying to wrap my head around webpack, and coming from Gulp it's quite confusing. My project structure looks like:
./root
-- src
-- styles.scss
-- bin
-- node_modules
-- webpack.config.js
So just something super simple, I want to compile the styles.scss in the src directory and output it to the bin directory. I installed the following loaders:
style-loader
css-loader
sass-loader (also installed node_sass as a dependency)
Now I know I'm not grasping something very fundamental of Webpack here but here's my webpack.config.js:
module.exports = {
entry: './src/styles.scss',
output: {
path: './bin',
filename: 'styles.css'
},
module: {
loaders: [
{
test: /\.scss$/,
loaders: ["style", "css", "sass"]
}
]
}
};
When I run webpack in the root of my directory it looks like it works. But the styles.css file looks like it contains a bunch of JavaScript code. So I don't understand that and need some clarity. I'm vaguely guessing that you can't use webpack if you don't have any JavaScript files in your project (besides webpack.config.js of course...
I am by far no webpack expert, but to my understanding, this is exactly what webpack is supposed to do, according to it's own documentation:
Loaders
webpack can only process JavaScript natively, but loaders are used to
transform other resources into JavaScript. [...]
What this means is, even if you only include SCSS-Files, webpack will convert them into a JavaScript-File, which can then be included just like any other JS-File.
For example, if you changed your styles.css into styles.js, you would call it in the head of html with
<head>
...
<script type="application/javascript" src="styles.js" charset="utf-8"></script>
...
</head>
Despite this, your CSS, although called as and wrapped in JavaScript, will still be correctly treated as CSS.
Why would you want to do this?
Basically to save calls to the server.
Webpack gives you the opportunity, to bundle your JS, your [S]CSS and many other things into a single JS-File, which you will be able to fetch with a single call to the server, therefore saving lots of round-trip-times.
Still, the browser will interpret all the resources accordingly.

RequireJS shim config in webpack

I want to port my requirejs web application to webpack module bundler. The app use several non AMD libraries (such jquery and bootstrap). RequireJS maintains such libraries via shim configuration. How I can declare dependincies for non AMD libraries in webpack?
I'm in the process of doing the same. It's practically as you would any AMD module. To use stringified templates put into AngularJS' $templateCache as an example:
Templates are generated in non-AMD format wrapped in an IIFE, pushed into a .tmp dir, then requested as per any module:
define([
'./module',
'templates/ubCampaignEditor'
]
As to keep definitions clean, I've created a resolve.alias named templates, in the Webpack config:
resolve: {
alias: {
templates: path.join(__dirname, '.tmp/templates')
}
}

Requirejs is looking in wrong path

This is a config file in the /themes/ifd/js/ folder:
require.config({
// Initialize the application with the main application file
deps: ['plugins/console', 'main'],
baseUrl: '/themes/ifd/js/components'
paths: {
jquery: 'jquery/jquery.min',
flexslider: 'flexslider/jquery.flexslider-min',
easydropdown: 'easydropdown/jquery.easydropdown.min',
bpopup: 'bpopup/jquery.bpopup.min',
jqrangeslider: 'jqrangeslider/jQRangeSlider',
jqueryui: 'jquery-ui/js/jquery-ui-1.10.4.custom.min'
// More additional paths here
},
shim: {
jqueryui: 'jquery'
},
// Prevent caching issues, by adding an additional URL argument
urlArgs: 'bust=' + (new Date()).getDate()
});
I've got a main.js file in the /themes/ifd/js folder too:
require([
// Require the modules
'modules/module',
'jquery',
'flexslider',
'easydropdown',
'bpopup',
'jqueryui',
'jqrangeslider'
], function (module) {
'use strict';
// Rest of a file
And rest of files (modules?) are inside /themes/ifd/js/components:
Screenshot of list of files
In my HTML I have:
<script data-main="/themes/ifd/js/main" src="/themes/ifd/js/requirejs.js"></script>
The messages I see in Chrome console:
GET http://DOMAIN/themes/ifd/js/jquery.js 404 (Not Found) requirejs.js:34
GET http://DOMAIN/themes/ifd/js/flexslider.js 404 (Not Found)
I can't find what is wrong and why it doesn't search in components directory...
The entry point for requirejs is the main module specified in the html file.
<script data-main="/themes/ifd/js/main" src="/themes/ifd/js/requirejs.js"></script>
requirejs loads '/themes/ifd/js/main.js' 1st. Now in the main.js file, require([...]) try to load in the module specified in the args but requirejs won't be able to find them.
The reason is that requirejs does not know about them since require.config (...) is not executed.
Need to have 'require.config (...)' in '/themes/ifd/js/main.js' to do all the settings
Here is a working example. It includes Requirejs, jQueryMobile, Backbone, and Marinonette.
In the index.html file, you need to specify the main module for requirejs to load.
<script type="text/javascript" data-main="js/main" src="js/libs/require-2.1.2.min.js"></script>
In this example, the main module is under "js/main.js"
Inside, main.js, you specify the require.config and use define to load your modules.
The network activity you show us indicates that your configuration is completely ignored by RequireJS. And you say "Then i have that in my html":
<script data-main="/themes/ifd/js/main" src="/themes/ifd/js/requirejs.js"></script>
You've shown the contents of /themes/ifd/js/main.js but it does not include your configuration, which apparently is in a different file.
The solution here would be to move your call to require.config into your main.js file, before your call to require.
It looks like you're just loading main.js and never telling RequireJS to use your config.
This RequireJS issue lists several ways to load both a config and a main -
put the config on the HTML before you require the top-level module.
load the config.js with another tag.
do a nested require() on the HTML file (require config than require your main).
do a nested require() inside main.js.
keep the configuration inside main.js
The best approach will vary based on your project structure, I've been doing 5 way more often than the others since I usually have a single entry-point for all pages, but in some cases I used 1 and 2.
Further down the page some code examples of these approaches are also shown.

Use RequireJS config file as the build file?

I've got some paths configured in require-config.js as follows:
var require = {
baseUrl: '/javascript',
paths: {
'jquery': 'jquery/jquery-1.8.1.min'
// etc. -- several paths to vendor files here
},
}
I am trying to get the optimization working for deployment. The docs say I should have a build.js that looks something like this:
({
baseUrl: 'javascript',
paths: {
'jquery': 'jquery/jquery-1.8.1.min'
},
name: 'main',
out: 'main-build.js'
})
Is there a way to have the optimizer read my config file instead of (or in addition to) build.js? I don't want to have to manually keep the paths configured the same in both files if they change.
I tried to just run node r.js -o path/to/require-config.js, but it threw an error, "malformed: SyntaxError: Unexpected token var"
Edit: for clarification, my require-config.js file is the config only, not my main module. I did this so I could use the same configuration but load a different main module when unit testing.
You'll need to adjust the way your config options are defined. Taken from the RequireJS documentation:
In version 1.0.5+ of the optimizer, the mainConfigFile option can be used to specify the location of the runtime config. If specified with the path to your main JS file, the first requirejs({}), requirejs.config({}), require({}), or require.config({}) found in that file will be parsed out and used as part of the configuration options passed to the optimizer:
So basically you can point your r.js build file to your config options that will also be shared with the browser.
You will need to make use of the mainConfigFile option
For other's reference:
https://github.com/jrburke/r.js/blob/master/build/example.build.js
The build settings (no need to repeat your config.js lib inclusions here):
baseUrl: 'app',
name: 'assets/js/lib/almond', // or require
// Read config and then also build it into the app
mainConfigFile: 'app/config.js',
include: ['config'],
// Needed for almond (and does no harm for require)
wrap: true,

dose requirejs need all JS files to support AMD

i'm reading little about requireJS and trying to understand it.
What i want to know:
Should i structure my files in specific way or pattern like Module-Pattern ??
When working with libraries should these files support AMD ?
Thanks Alot for your help.
You can structure your files any way you see fit. RequireJS loads the script file referenced in the data-main attribute of the script tag that loads require.js. From that file you're free to require whatever modules you want.
Libraries don't need to support AMD. You can use the shim config to load modules that export value to the global scope (i.e. normal javascript files).
Mostly I'm setting up a require.js project with a structure as below:
root
js
modulesType1
mod1
mod2
modulesType2
mod1
mod2
app.js
bootstrap.js
lib
require
require.js
lib1
lib1.js
css/img/partials/...
index.html
And an initial bootstrap.js a have a require.config object and an initial require:
/*global define, require */
require.config({
baseUrl: 'js',
paths: {
lib1: '../lib/lib1/lib1'
},
shim: {
lib1: ['something']
}
});
require(['lib1', 'app'], function (lib1, app) {
app.doSth();
});
In your html page you only need one script tag with a data-main attribute:
<body>
...
<script type="text/javascript" src="lib/require/require.js" data-main="js/bootstrap"></script>
</body>
Edit: modules don't have to be AMD compliant, but if they are under your own control, it is better to make them AMD compliant. You can make third party non-AMD libraries loadable using the shim property in require.config.

Resources