JavaScript Modular-require.js,r.js and packaged publishing

Source: Internet
Author: User
Tags node server rsync start node server

In the two articles of JavaScript modularization and Closure and javascript-module-pattern-in-depth, the basic idea of modularization is mentioned, but in the actual project, the Modularization and the division of the project personnel, the development, the package release, the performance optimization, Engineering management has a close relationship, so important things, in JavaScript big line of the today, there is no way to mature solutions, so from my practical experience, from the modular talk about engineering, share their own experience.

This article is mainly about the use of require.js and R.js in the project, will not involve engineering problems, the familiar crossing can skip this article. For Require.js basic usage of unfamiliar friends, you can look at this blog:asynchronous_module_definition

The modularity of JavaScript

Popular modular solutions are now available in a number of categories, mainly in the following

    • AMD: Today's topic, the AMD specification is an important attempt at JavaScript development, which unifies JavaScript's module definition and loading mechanisms in a simple and elegant way, and quickly receives recognition and adoption of many frameworks. This is good news for developers, and through AMD we have lowered the barriers to learning and using various frameworks, being able to define and use modules in a unified way, improve development efficiency, and reduce application maintenance costs.
    • CommonJS:node.js in a way that requires packaging tools to work with the front end. On the back end is more useful.
    • CMD & sea.js: Domestic cattle man engaged. LABJS, Requirejs, Seajs which is the best use? Why?

The modularity of JavaScript needs to address several issues

    • Defining modules
    • Management module Dependencies
    • Loading modules
    • Load optimization
    • Code debugging support

For an intuitive understanding of how require.js and r.js have been solving these problems for a long time, let's start with an example. Download Example-multipage-shim

Code structure

Let's take a look at the basic structure of a multi-page project based on Requirejs:


Example-multipage-shim file Structure


Let's look at how to solve the problem of JS Modularization.

Defining modules

Look at Base.js.

define(function () {    function controllerBase(id) {        this.id = id;    }    controllerBase.prototype = {        setModel: function (model) {            this.model = model;        },        render: function (bodyDom) {            bodyDom.prepend(‘

You can define it using define. We do not need to manually export global variables.

Management module Dependencies

Look at C1.js.

define([‘./Base‘], function (Base) {    var c1 = new Base(‘Controller 1‘);    return c1;});

Can be seen by [‘./Base‘] injecting dependencies.
Look at the main1.js.

define(function (require) {    var $ = require(‘jquery‘),        lib = require(‘./lib‘),        controller = require(‘./controller/c1‘),        model = require(‘./model/m1‘),        backbone = require(‘backbone‘),        underscore = require(‘underscore‘);    //A fabricated API to show interaction of    //common and specific pieces.    controller.setModel(model);    $(function () {        controller.render(lib.getBody());        //Display backbone and underscore versions        $(‘body‘)            .append(‘<div>backbone version: ‘ + backbone.VERSION + ‘</div>‘)            .append(‘<div>underscore version: ‘ + underscore.VERSION + ‘</div>‘);    });});

You can also load a dependent module by require (COMMONJS style)

Loading modules

Take a look at how to start and see page1.html

<!DOCTYPE html>

We see the script introduction of tags First require.js , and then use the requirejs loading modules, which are also script referenced by tags, so requirejs help us manage the loading of files. You can use the data-main properties to load, and you can read the documentation in detail.
Let's look at the effect of the operation.


Run effect


Can see requirejs help our home in all modules, we can better organize JavaScript code.

Optimized loading

After we have modularized the code, we do not want to increase the number of requests, which will slow down the performance of the Web page (this is asynchronous loading, but the browser has too many asynchronous requests or problems), so we want to merge the code.
Use r.js :

node r.js -o build.js

Using R.js


Look at the results:


After building


After the build, our code has been processed.

Look at the running effect.


Reduction of requests


Can be seen by r.js helping us refine the request (by merging the files).

How to configure
    • Requirejs How to configure, we look at Common.js
      requirejs.config({  baseUrl: ‘js/lib‘, 从这个位置加载模块  paths: {      app: ‘../app‘   },  shim: {      backbone: {          deps: [‘jquery‘, ‘underscore‘],          exports: ‘Backbone‘      },      underscore: {          exports: ‘_‘      }  }});
Properties meaning
BaseUrl Where to load the module
App: '.. /app ' Like this ' app/sub ', look for sub modules in the app directory
Shim Globally exported libraries, packed here

You can see the Chinese manual for a more detailed explanation.

    • R.js How to configure, we look at Build.js
      There is a full set of configuration instructions Example.build.js, how do we configure ourselves.
{appdir: '. /www ', Mainconfigfile: '. /www/js/common.js ', dir: '.        /www-built ', modules: [//first set up the common build layer. {//module names is relative to BaseUrl name: '. /common ',//list common dependencies here.            Only need to list//top level dependencies, "include" would find//nested dependencies. Include: [' jquery ', ' app/lib ', ' app/controller/base ', ' app/ Model/base ']},//now set up a build layer for each main layer, but exclude//the common One. "Exclude" would exclude nested//the nested, built dependencies from "common". Any//"exclude" so includes built modules should be//listed before the build layer that wants to exclude        It. The "Page1" and "Page2" modules are **not** the targets of//the optimization, because Shim Config was in play, an        Dshimmed dependencies need to maintain their load order. In this example, Common.js'll hold jquery, so backbone//needs to be delayed from loading until Common.js Finis        Hes.        That loading sequence was controlled in page1.html. {//module names is relative to baseurl/paths config name: ' app/main1 ', exclude: ['.. /common '}, {//module names is relative to BaseUrl name: ' App/main2 ', ex Clude: [' ... /common '}]}

We mainly look at modules the following definition of the array, is actually a file dependency, R.js will use the relationship here, merge files. Detailed configuration meaning can be seen in the document

Tip: R.js can also optimize CSS.

How to Debug

After the previous code has been optimized, debugging is painful, and here we can use Sourcemap technology to debug the optimized code. Do the following.

    1. Modify the Build.js to add the following configuration
      generateSourceMaps: true,preserveLicenseComments: false,optimize: "uglify2",
    2. Re-build
      node r.js -o build.js
    3. Open Browser support
      It is best to use the Firefox browser, chrome from the local file open HTML does not work properly sourcemap. Just use Firefox to browse it.


      Firefox support Sourcemap


      Can see the code can be loaded non-optimized, some people will ask, this do not request many times? Optimize one copy, not optimize it, so it's not worse. In fact, only when you debug, turn on this feature will request the corresponding Sourcemap file, so it is not wasted for users.

    4. Write a server let chrome also support
      Chrome itself is support for source map, that is, the right to open files directly from the hard disk permissions have special treatment. file://many things can not be done with the path of the beginning. So let's do a simple server.

Add a server.js file under the Tools directory

var http = require (' http '), url = require (' URL '), Path = require (' path '), FS = require (' FS '), Port = PROCESS.A RGV[2] | | 8888, types = {' html ': ' text/html ', ' js ': ' Application/javascript '};http.createserver (function (requ        EST, response) {var uri = Url.parse (request.url). Pathname, filename = path.join (__dirname, '.. ', URI);    Console.log (filename); fs.exists (filename, function (exists) {if (!exists) {Response.writehead (404, {' Content-type ': ' TEXT/PL            Ain '});            Response.Write (' 404 Not found\n ');            Response.End ();        Return        } var type = Filename.split ('. ');        Type = Type[type.length-1];        Response.writehead ($, {' Content-type ': types[type] + '; Charset=utf-8 '});    Fs.createreadstream (filename). pipe (response); });}).  Listen (parseint (port)); Console.log (' Static file server running at\n = http://localhost: ' + port + '/\nctrl + C to Shutdown ');

Turn on Chrome support Sourcemap


Turn on Chrome support

Use node to start the server


Start node Server

Debugging in the browser


Chrome requires server support publishing

This article is in terms of modularity, and release does not matter, but all written here, the program to publish it, the back of this article to discuss the project, you can see how this article process improved.
There are just a few ways to publish this:

    1. Windows Server directly to the remote past, copy a bit better. The Web Deploy tool is also useful.
    2. Linux uses FTP to remote, then copy.
    3. Use Rsync.

Let's take a look at the third kind. We use R.js to optimize how to publish to the server later. We follow the method recommended by deployment-techniques this article to say. This method of publishing is presented under these considerations.

    1. The built code is not submitted to version control. The reason is mainly for good maintenance, the pre-submission build is easy to forget, and the submission of optimized code if the conflict is difficult to diff,merge.
    2. It is not good to generate the built code on the server using R.js, because R.js will delete the directory and recreate it, so if the project is large, there will be a lot of 404 errors in the service for some time.

So we figured out how to synchronize the folders with incremental updates. The main reliance on the rsync command.
It is recommended to use the Grunt tool to package and then run a command to sync the folder. Let's look at the code.

/** * Gruntfile.js */module.exports = function (grunt) {//Do grunt-related things in here var Requirejs = require ("        Requirejs "), exec = require (" child_process "). Exec, fatal = grunt.fail.fatal, log = Grunt.log, VERBOSE = grunt.verbose, fs = require (' FS '), Json5 = Fs.readfilesync ("./build.js", ' UTF8 '), JSON5 = R    Equire (' json5 '),//Your r.js build Configuration Buildconfigmain = Json5.parse (JSON5); Transfer the build folder to the right location on the server Grunt.registertask ("Transfer", "TRANSFE R the build folder to.            /website/www-built and remove it, function () {var done = This.async (); Delete the build folder locally after transferring exec ("Rsync-rlv--delete--delete-after. /www-built. /WebSite && RM-RF. /www-built ", function (err, stdout, stderr) {if (err) {Fatal (" Pr Oblem WitH rsync: "+ err +" "+ stderr);                    } verbose.writeln (stdout);                    Log.ok ("Rsync complete.");                Done ();        });    }    ); Build static assets using R.js grunt.registertask ("Build", "Run the R.js Build script", Functi            On () {var-done = This.async ();            Log.writeln ("Running build ...");                Requirejs.optimize (buildconfigmain, function (output) {Log.writeln (output);                Log.ok ("Main build Complete.");            Done ();            }, function (err) {fatal ("Main Build Failure:" + err);            });        This was run after the build completes Grunt.task.run (["Transfer"]); }    );};

Run results
Can see a new website folder, and the built intermediate files to sync to this folder, and the website file is available on the remote server, is not very convenient?


Publish Results

The above changes can be downloaded from here, you can play with Requirejs-deploy-demo

Summarize

As can be seen, through the require.js,r.js can be very good for the development of modular language, using Grunt,rsync, we can complete the build and release capabilities.



Shenyin
Links: http://www.jianshu.com/p/7186e5f2f341
Source: Pinterest
Copyright belongs to the author. Commercial reprint please contact the author for authorization, non-commercial reprint please specify the source.

JavaScript Modular-require.js,r.js and packaged publishing

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.