πŸ“œ ⬆️ ⬇️

JavaScript Modules



This is the third publication based on our internal conference Sync.NET . The first publication was devoted to multithreading in .NET , the second - to reactive extensions .

When developing the front-end part of an application in JavaScript, we may encounter a number of traditional problems. All of them are solved using modular approaches. Below we consider the most popular approaches for describing modules in JavaScript that exist today.

So, what problems are meant:
')
Large files . Quite often a situation arises when a project has files named in the style of app.js or common.js, in which everything is simply dumped into one heap: functions, helpers, widgets, etc. Working and maintaining code in such files is quite difficult. You have to constantly scroll back and forth, looking for the right piece of code, put a lot of bookmarks using the IDE, so as not to lose the right places in the file. There is also a tendency that the larger the file size, which contains a bunch of common logic, the faster it continues to grow. Plus, in a large team, this can cause permanent conflicts in the version control system.

Dependencies and connection order . Often the JS-code in the application is divided into several files. We use plugins that depend on libraries; libraries that depend on other libraries; and the code written in his own hand, already depends on that and the other. Therefore, the developer is forced to strictly follow the order of connection of JS-files and regularly spend time and energy on their ordering. If the order is broken, we get an error. In any case, errors that occur due to improper file ordering are usually fairly easy to notice. In this case, most often we just get an exception in the browser, for example, $ is undefined .

Duplication of the connection of the same files can become more difficult in detecting errors. For example, there is a file with a piece of code that hangs an event handler on any dom element. Your colleague may not notice that this file has already been connected, and connects it again. As a result, the handler will be executed twice, which can lead to an unpleasant error, which is rather difficult to notice right away.

Variables in the global scope . Problems with global variables are that they will be available in all the code of your application or page. They are in the global namespace, and there is always a chance of naming collisions when two different parts of an application define global variables with the same name, but for different purposes. Plus, by declaring variables in the global scope, we are polluting the window object. And referring each time to a global variable, the JS interpreter has to look for it in a bloated window object, which affects the performance of the code.

Unstructured and not obvious code . Another rather unpleasant situation is when there are no clear boundaries separating logical pieces of code. When, without delving into the code, you cannot immediately tell what other parts of the application it uses.

First modules


Initially, JS did not have the ability to create real modules. Although previously it was not required: the sites had a relatively small amount of JS-code. Basically it was necessary to β€œscrew the carousel” somewhere, somewhere a beautiful animated menu, and that’s it. But then the web-based applications on the complexity of the interface and rich functionality began to catch up with traditional desktop. And then the so-called β€œmodule” pattern became popular.

 var SomeModule = (function() { var count = 0; function notNegative(num) { return num < 0 ? 0 : num; } return { getCount: function() { return count; }, setCount: function(newCount) { count = notNegative(newCount); } }; })(); 

This approach works quite simply: an immediately-called anonymous wrapper function is created that returns the module's public interface, and the rest of the implementation is encapsulated in a closure. This helps to solve two problems of the above: the number of global variables is greatly reduced, and the code itself becomes a little clearer due to the fact that we delimit it into logical pieces. But the problem of managing dependencies and connecting files remains open.

Commonjs


The first standard, which describes the API for creating and connecting modules, was developed by the CommonJS working group. This standard was coined for use in server-side JS, and its implementation can be seen, for example, in node.js.

 var logger = require('../utils/logger'); var MyDependency = require('MyDependency'); var count = 0; function notNegative(num) { return num < 0 ? 0 : num; } module.exports = { getCount: function() { return count; }, setCount: function(newCount) { count = notNegative(newCount); logger.log('Count changed to {0}', count); } }; 

To connect dependencies, the global require() function is used, which takes the first parameter as a string with the path to the module. To export the module interface, we use the exports property of the module object. And when this module is connected as a dependency using the require function, somewhere in the code of another module, the same function will return the exported object.

This approach solves all of the above problems. No wrappers are needed, each file is a separate module with its own scope. The source code can be broken into small logical units. And each module clearly defines all its dependencies.

BUT! In the browser, just like that, this syntax will not work. To do this, use a special collector. For example, popular browserify or Brunch , which work on node.js. These tools are quite convenient, their functionality is not limited only to the ability to create CommonJS-modules, and many developers prefer to use them in their projects. The essence of them is the same: the collector goes through the module dependency tree and collects everything into one file, which in turn will be loaded by the browser. Even when developing in debug mode, you need to constantly run the collector from the command line, or, more conveniently, to run a watcher, which will monitor changes in files and automatically assemble. It is worth noting that debugging does not have to source files, but what the collector will generate. If you are not planning to debug your code in older browsers, this will not be a problem, because the collectors are able to generate Source Maps , thanks to which the resulting compressed file will be linked to the sources. This will allow you to debug as if you are working with the source code itself. Also, building into one file is not always good. For example, if we want to load the module remotely, from a CDN, or load a piece of code only on demand.

The future is now


In the new standard ECMAScript 6, in addition to all the cool stuff, described a new syntax for creating and connecting modules.

 // lib/math.js let notExported = 'abc'; export function sum(x, y) { return x + y; } export const PI = 3.14; 

One module, as in CommonJS, is one file. The scope is also limited to this file. The export keyword exports the desired values ​​to the rest of the program. It can be used anywhere: in the middle of the module code or at the end, exporting everything in bulk.

 // lib/calc.js let notExported = 'abc'; function square(x) { return x * x; } const PI = 3.14; export {square, PI}; 

To connect the module, use the keywords import , from and as . You can import only one value you need ...

 //app.js import {sum} from 'lib/math'; console.log(sum(3, 5)); 

... or several at once.

 //app.js import {sum, PI} from 'lib/math'; console.log('2Ο€ =' + sum(PI, PI)); 

Alternatively, you can import the entire module as an object with all exported values.

 //app.js import 'lib/calc' as calc; console.log(calc.square(calc.PI)); 

It is possible to change the names of variables with imported values, which can be useful if you import values ​​with the same name from different modules.

 //app.js import {square} from '../shapes'; import {square as sq} from 'lib/calc'; console.log(sq(3)); 

In order, for example, to allocate one file for one class, it is convenient to determine the exported default value.

 // models/User.js export default class { constructor(id, name) { this.id = id; this.name = name; } } 

To import the default value, it’s enough not to use curly brackets.

 //app.js import User from 'models/User'; var user = new User(12, 'John'); 

In the examples, the so-called declarative syntax was used. It is also possible to use a software interface that allows you to load modules asynchronously and by condition. To do this, use System.import() .

 import $ from 'lib/jquery'; if($('html').hasClass('ie')) { System.import('lib/placeholder').then(function(placeholder){ placeholder($('input')); }); } $('.logo').show(600); 

As a single parameter, you must pass the path to the module. As a result of executing System.import() , a Promise object is returned. Thus, the thread of execution is not blocked and the code that is not related to the import of the module will be executed further.

Browsers do not really support the new syntax, but the ability to use already exists. This will help you one of the special translators, for example, Babel . As in the case of CommonJS, you need to run the translator from the command line or install watcher, thanks to which the source code written in ES6, when changed, will be converted to a cross-browser form.

Some developers are already using the new syntax, and you can definitely say that this approach is the future. Most do not dare to use new technology in real projects.

AMD


For several years, the approach called Asynchronous Module Definition allows you to split application code into modules in all popular browsers (IE6 +), using only browser capabilities.

AMD is a development approach that allows you to create modules so that they and their dependencies can be loaded asynchronously and in parallel. This allows you to speed up the loading of the page, since the download of JS-modules will not block the download of the rest of the site content. Plus, AMD makes it possible to load modules as they are needed. For example, there is a page with a complex modal window in which a lot of logic is concentrated: different β€œwizards”, several forms, etc. It is assumed that the window will be used very rarely. In this case, AMD allows you to download JS-code for this window not with the page, but before it is opened by the user.

Simply put, AMD’s approach comes down to describing modules with the define function and connecting them with require .

 define([id], [dependencies], callback); require(modules, [callback]); 

The most popular implementation of the AMD approach is the RequireJS library.

RequireJS


You can download the library from the official site , or you can use any popular package manager. For example, with NuGet, you can install it by running the Install-Package RequireJS command.

In RequireJS, the require and define methods have several variations.

The define method can take three parameters:

 // app/index.js define('app', ['jquery', 'utils/print'], function($, print) { var $body = $('body'); var App = function(name) { this.name = name; this.content = $body; }; App.prototype.init = function() { print(this.name + 'body', this.content); } return new App('MyApp'); }); 

The first parameter is the id of the module. id can be used instead of the file path to connect the module as a dependency of another module, but only when the file with the module code has already been loaded in the browser. Actually, this is an optional parameter. And not just optional, it is even undesirable to use in development. Rather, it is needed for correct dependency management in the event that several modules are defined in one file at once. The optimization tool used to build modules into one file for production automatically adds these id.

define can only accept the other two parameters:

 // app/index.js define(['jquery', 'utils/print'], function($, print) { var $body = $('body'); var App = function(name) { this.name = name; this.content = $body; }; App.prototype.init = function() { print(this.name + 'body', this.content); }; return new App('MyApp'); }); 

In this case, the first parameter is an array of module dependencies. To determine the dependency, you just need to add to the array a string containing the path to the module or its id. The last parameter is the factory function that is creating the module. This function will be executed only when all dependencies of the module are loaded, and takes exported values ​​from all dependencies as arguments. Inside the function is the implementation of the module, which is not accessible from the outside. At the end, the module itself is exported by calling return . You can export anything you want: a normal function, a constructor, an object, a string; in general, any type of data. It is important to understand that the factory function is executed only once, when we first connect the module as a dependency. The remaining modules, which also connect this dependency, will receive the already cached value of the module.

There is one problem - the call to define might look like this:

 // app/index.js define(['jquery', 'utils/print', 'modules/Module1', 'modules/Module2', 'modules/Module3', 'modules/Module4', 'modules/Module5', 'modules/Module6', 'modules/Module7', 'modules/Module8', 'modules/Module9'], function($, print, Module1, Module2, Module3, Module4, Module5, Module6, Module7, Module8, Module9) { var $body = $('body'); var App = function(name) { this.name = name; this.content = $body; }; // ... }); 

This is pretty awkward. It is necessary to ensure that the order of the specified dependencies in the array coincides with the order of the arguments that the factory function accepts. Therefore, in RequireJS there is another variant of define , which allows you to pass only one parameter - the constructor function.

 // app/index.js define(function(require) { var $ = require('jquery'), print = require('utils/print'); var $body = $('body'); var App = function(name) { this.name = name; this.content = $body; }; App.prototype.init = function() { print(this.name + 'body', this.content); }; return new App('MyApp'); }); 

This option is similar to the CommonJS approach. The first argument will be passed to the so-called local function require . It is now possible to connect module dependencies by calling this function, and it will return those values ​​that the plug-in exports. It must be remembered that this syntax is functionally the same as the previous one. All dependency files that are connected by calling require will be loaded before the module factory function is executed. This is because when the module file is loaded into the browser, the loader searches for all local require calls using regular expressions. For this reason, the local call require cannot be used, for example, to load a module by condition.

You can also define a module as a simple object.

 // modules/module.js define({ id: 123, key: 'jquery', getValue: function() { return this.key; } }); 

Such modules are conveniently used as a set of constants.

In order to start executing client logic, you need to call the global require function.

 // main.js require(['app/index'], function(app) { app.init(); }); 

This variant of the require function differs from the local variant by the set of received parameters. In this case, the first parameter is to pass an array of plug-ins. Even if you need to connect only one module, you still need to transfer it in the array, otherwise the library recognizes it as a local call and there will be an error, since local calls are possible only within the definition of the module. The second optional parameter is a callback function, which, as in the case of define , will be executed as soon as all the necessary dependencies are loaded.

It is possible to make nested require calls within a callback function or within a module definition.

 // main.js require(['app/index', 'utils/browserName'], function(app, browserName) { app.init(); if(browserName == 'IE') { require(['app/fix-' + browserName]); } }); 

Another significant difference of this type of require call is that the included files will start loading only when the execution flow reaches the function call. Due to this, it is possible to load modules only on demand or by condition.

Connection


To work, you need only one single tag.
   HTML- .     JS-  . 

<!DOCTYPE html> <html> <head> <script data-main="./main" src="lib/require.js"></script> </head> <body> <h1>RequireJS Example</h1> <form> <input /> </form> </body> </html>

data-main main.js ( .js RequireJS ) JS- .

RequireJS , , requirejs.config .

// main.js requirejs.config({ baseUrl: 'Scripts', paths: { jquery: 'jquery-1.11.2', modules: 'app/modules', utils: 'app/utils' }, shim: { 'jquery.validate.unobtrusive': { deps: ['jquery', 'jquery.validate'], exports: '$.validator.unobtrusive' } } }); require(['app/index'], function (app) { app.init(); });
baseUrl , JS-. , . , , require.js. path «» , .

AMD, define . , . , RequireJS . shim , deps () exports ( ).

Text
RequireJS JS-, , , HTML, text .

// app/views/module.html <h3>Module:</h3> <h2>"{name}" is loaded</h2> // module.js define(function (require) { var view = require('text!app/views/module.html'); var name = 'First Module'; return { getHTML: function () { return view.replace('{name}', name); }, getName: function () { return name; } }; });

require module.html , HTML- . , HTML- JS-.


, , production. r.js, require.js.

JS, node.js. , . app.build.js, JS- .

// app.build.js ({ baseUrl: ".", dir: '../Scripts-build', mainConfigFile: 'main.js', name: "main", preserveLicenseComments: false, wrapShim: true })
baseUrl , . dir β€” . main β€” , RequireJS. preserveLicenseComments β€” , wrapShim β€” shim- define . : example.build.js .

>node r.js -o app.build.js

, , pre-build event Visual Studio, JS- , .

Profit
, , RequireJS:

, HTML- debug-
HTML- . JS- .

<!DOCTYPE html> <html> <head> <script data-main="./main" src="lib/require.js"></script> </head> <body> <h1>RequireJS Example</h1> <form> <input /> </form> </body> </html>

data-main main.js ( .js RequireJS ) JS- .

RequireJS , , requirejs.config .

// main.js requirejs.config({ baseUrl: 'Scripts', paths: { jquery: 'jquery-1.11.2', modules: 'app/modules', utils: 'app/utils' }, shim: { 'jquery.validate.unobtrusive': { deps: ['jquery', 'jquery.validate'], exports: '$.validator.unobtrusive' } } }); require(['app/index'], function (app) { app.init(); });
baseUrl , JS-. , . , , require.js. path «» , .

AMD, define . , . , RequireJS . shim , deps () exports ( ).

Text
RequireJS JS-, , , HTML, text .

// app/views/module.html <h3>Module:</h3> <h2>"{name}" is loaded</h2> // module.js define(function (require) { var view = require('text!app/views/module.html'); var name = 'First Module'; return { getHTML: function () { return view.replace('{name}', name); }, getName: function () { return name; } }; });

require module.html , HTML- . , HTML- JS-.


, , production. r.js, require.js.

JS, node.js. , . app.build.js, JS- .

// app.build.js ({ baseUrl: ".", dir: '../Scripts-build', mainConfigFile: 'main.js', name: "main", preserveLicenseComments: false, wrapShim: true })
baseUrl , . dir β€” . main β€” , RequireJS. preserveLicenseComments β€” , wrapShim β€” shim- define . : example.build.js .

>node r.js -o app.build.js

, , pre-build event Visual Studio, JS- , .

Profit
, , RequireJS:

, HTML- debug-
   HTML- .     JS-  . 

<!DOCTYPE html> <html> <head> <script data-main="./main" src="lib/require.js"></script> </head> <body> <h1>RequireJS Example</h1> <form> <input /> </form> </body> </html>

data-main main.js ( .js RequireJS ) JS- .

RequireJS , , requirejs.config .

// main.js requirejs.config({ baseUrl: 'Scripts', paths: { jquery: 'jquery-1.11.2', modules: 'app/modules', utils: 'app/utils' }, shim: { 'jquery.validate.unobtrusive': { deps: ['jquery', 'jquery.validate'], exports: '$.validator.unobtrusive' } } }); require(['app/index'], function (app) { app.init(); });
baseUrl , JS-. , . , , require.js. path «» , .

AMD, define . , . , RequireJS . shim , deps () exports ( ).

Text
RequireJS JS-, , , HTML, text .

// app/views/module.html <h3>Module:</h3> <h2>"{name}" is loaded</h2> // module.js define(function (require) { var view = require('text!app/views/module.html'); var name = 'First Module'; return { getHTML: function () { return view.replace('{name}', name); }, getName: function () { return name; } }; });

require module.html , HTML- . , HTML- JS-.


, , production. r.js, require.js.

JS, node.js. , . app.build.js, JS- .

// app.build.js ({ baseUrl: ".", dir: '../Scripts-build', mainConfigFile: 'main.js', name: "main", preserveLicenseComments: false, wrapShim: true })
baseUrl , . dir β€” . main β€” , RequireJS. preserveLicenseComments β€” , wrapShim β€” shim- define . : example.build.js .

>node r.js -o app.build.js

, , pre-build event Visual Studio, JS- , .

Profit
, , RequireJS:

, HTML- debug-
HTML- . JS- .

<!DOCTYPE html> <html> <head> <script data-main="./main" src="lib/require.js"></script> </head> <body> <h1>RequireJS Example</h1> <form> <input /> </form> </body> </html>

data-main main.js ( .js RequireJS ) JS- .

RequireJS , , requirejs.config .

// main.js requirejs.config({ baseUrl: 'Scripts', paths: { jquery: 'jquery-1.11.2', modules: 'app/modules', utils: 'app/utils' }, shim: { 'jquery.validate.unobtrusive': { deps: ['jquery', 'jquery.validate'], exports: '$.validator.unobtrusive' } } }); require(['app/index'], function (app) { app.init(); });
baseUrl , JS-. , . , , require.js. path «» , .

AMD, define . , . , RequireJS . shim , deps () exports ( ).

Text
RequireJS JS-, , , HTML, text .

// app/views/module.html <h3>Module:</h3> <h2>"{name}" is loaded</h2> // module.js define(function (require) { var view = require('text!app/views/module.html'); var name = 'First Module'; return { getHTML: function () { return view.replace('{name}', name); }, getName: function () { return name; } }; });

require module.html , HTML- . , HTML- JS-.


, , production. r.js, require.js.

JS, node.js. , . app.build.js, JS- .

// app.build.js ({ baseUrl: ".", dir: '../Scripts-build', mainConfigFile: 'main.js', name: "main", preserveLicenseComments: false, wrapShim: true })
baseUrl , . dir β€” . main β€” , RequireJS. preserveLicenseComments β€” , wrapShim β€” shim- define . : example.build.js .

>node r.js -o app.build.js

, , pre-build event Visual Studio, JS- , .

Profit
, , RequireJS:

, HTML- debug-

HTML- . JS- .

<!DOCTYPE html> <html> <head> <script data-main="./main" src="lib/require.js"></script> </head> <body> <h1>RequireJS Example</h1> <form> <input /> </form> </body> </html>

data-main main.js ( .js RequireJS ) JS- .

RequireJS , , requirejs.config .

// main.js requirejs.config({ baseUrl: 'Scripts', paths: { jquery: 'jquery-1.11.2', modules: 'app/modules', utils: 'app/utils' }, shim: { 'jquery.validate.unobtrusive': { deps: ['jquery', 'jquery.validate'], exports: '$.validator.unobtrusive' } } }); require(['app/index'], function (app) { app.init(); });
baseUrl , JS-. , . , , require.js. path «» , .

AMD, define . , . , RequireJS . shim , deps () exports ( ).

Text
RequireJS JS-, , , HTML, text .

// app/views/module.html <h3>Module:</h3> <h2>"{name}" is loaded</h2> // module.js define(function (require) { var view = require('text!app/views/module.html'); var name = 'First Module'; return { getHTML: function () { return view.replace('{name}', name); }, getName: function () { return name; } }; });

require module.html , HTML- . , HTML- JS-.


, , production. r.js, require.js.

JS, node.js. , . app.build.js, JS- .

// app.build.js ({ baseUrl: ".", dir: '../Scripts-build', mainConfigFile: 'main.js', name: "main", preserveLicenseComments: false, wrapShim: true })
baseUrl , . dir β€” . main β€” , RequireJS. preserveLicenseComments β€” , wrapShim β€” shim- define . : example.build.js .

>node r.js -o app.build.js

, , pre-build event Visual Studio, JS- , .

Profit
, , RequireJS:

, HTML- debug-

HTML- . JS- .

<!DOCTYPE html> <html> <head> <script data-main="./main" src="lib/require.js"></script> </head> <body> <h1>RequireJS Example</h1> <form> <input /> </form> </body> </html>

data-main main.js ( .js RequireJS ) JS- .

RequireJS , , requirejs.config .

// main.js requirejs.config({ baseUrl: 'Scripts', paths: { jquery: 'jquery-1.11.2', modules: 'app/modules', utils: 'app/utils' }, shim: { 'jquery.validate.unobtrusive': { deps: ['jquery', 'jquery.validate'], exports: '$.validator.unobtrusive' } } }); require(['app/index'], function (app) { app.init(); });
baseUrl , JS-. , . , , require.js. path «» , .

AMD, define . , . , RequireJS . shim , deps () exports ( ).

Text
RequireJS JS-, , , HTML, text .

// app/views/module.html <h3>Module:</h3> <h2>"{name}" is loaded</h2> // module.js define(function (require) { var view = require('text!app/views/module.html'); var name = 'First Module'; return { getHTML: function () { return view.replace('{name}', name); }, getName: function () { return name; } }; });

require module.html , HTML- . , HTML- JS-.


, , production. r.js, require.js.

JS, node.js. , . app.build.js, JS- .

// app.build.js ({ baseUrl: ".", dir: '../Scripts-build', mainConfigFile: 'main.js', name: "main", preserveLicenseComments: false, wrapShim: true })
baseUrl , . dir β€” . main β€” , RequireJS. preserveLicenseComments β€” , wrapShim β€” shim- define . : example.build.js .

>node r.js -o app.build.js

, , pre-build event Visual Studio, JS- , .

Profit
, , RequireJS:

, HTML- debug-
   HTML- .     JS-  . 

<!DOCTYPE html> <html> <head> <script data-main="./main" src="lib/require.js"></script> </head> <body> <h1>RequireJS Example</h1> <form> <input /> </form> </body> </html>

data-main main.js ( .js RequireJS ) JS- .

RequireJS , , requirejs.config .

// main.js requirejs.config({ baseUrl: 'Scripts', paths: { jquery: 'jquery-1.11.2', modules: 'app/modules', utils: 'app/utils' }, shim: { 'jquery.validate.unobtrusive': { deps: ['jquery', 'jquery.validate'], exports: '$.validator.unobtrusive' } } }); require(['app/index'], function (app) { app.init(); });
baseUrl , JS-. , . , , require.js. path «» , .

AMD, define . , . , RequireJS . shim , deps () exports ( ).

Text
RequireJS JS-, , , HTML, text .

// app/views/module.html <h3>Module:</h3> <h2>"{name}" is loaded</h2> // module.js define(function (require) { var view = require('text!app/views/module.html'); var name = 'First Module'; return { getHTML: function () { return view.replace('{name}', name); }, getName: function () { return name; } }; });

require module.html , HTML- . , HTML- JS-.


, , production. r.js, require.js.

JS, node.js. , . app.build.js, JS- .

// app.build.js ({ baseUrl: ".", dir: '../Scripts-build', mainConfigFile: 'main.js', name: "main", preserveLicenseComments: false, wrapShim: true })
baseUrl , . dir β€” . main β€” , RequireJS. preserveLicenseComments β€” , wrapShim β€” shim- define . : example.build.js .

>node r.js -o app.build.js

, , pre-build event Visual Studio, JS- , .

Profit
, , RequireJS:

, HTML- debug-
HTML- . JS- .

<!DOCTYPE html> <html> <head> <script data-main="./main" src="lib/require.js"></script> </head> <body> <h1>RequireJS Example</h1> <form> <input /> </form> </body> </html>

data-main main.js ( .js RequireJS ) JS- .

RequireJS , , requirejs.config .

// main.js requirejs.config({ baseUrl: 'Scripts', paths: { jquery: 'jquery-1.11.2', modules: 'app/modules', utils: 'app/utils' }, shim: { 'jquery.validate.unobtrusive': { deps: ['jquery', 'jquery.validate'], exports: '$.validator.unobtrusive' } } }); require(['app/index'], function (app) { app.init(); });
baseUrl , JS-. , . , , require.js. path «» , .

AMD, define . , . , RequireJS . shim , deps () exports ( ).

Text
RequireJS JS-, , , HTML, text .

// app/views/module.html <h3>Module:</h3> <h2>"{name}" is loaded</h2> // module.js define(function (require) { var view = require('text!app/views/module.html'); var name = 'First Module'; return { getHTML: function () { return view.replace('{name}', name); }, getName: function () { return name; } }; });

require module.html , HTML- . , HTML- JS-.


, , production. r.js, require.js.

JS, node.js. , . app.build.js, JS- .

// app.build.js ({ baseUrl: ".", dir: '../Scripts-build', mainConfigFile: 'main.js', name: "main", preserveLicenseComments: false, wrapShim: true })
baseUrl , . dir β€” . main β€” , RequireJS. preserveLicenseComments β€” , wrapShim β€” shim- define . : example.build.js .

>node r.js -o app.build.js

, , pre-build event Visual Studio, JS- , .

Profit
, , RequireJS:

, HTML- debug-

HTML- . JS- .

<!DOCTYPE html> <html> <head> <script data-main="./main" src="lib/require.js"></script> </head> <body> <h1>RequireJS Example</h1> <form> <input /> </form> </body> </html>

data-main main.js ( .js RequireJS ) JS- .

RequireJS , , requirejs.config .

// main.js requirejs.config({ baseUrl: 'Scripts', paths: { jquery: 'jquery-1.11.2', modules: 'app/modules', utils: 'app/utils' }, shim: { 'jquery.validate.unobtrusive': { deps: ['jquery', 'jquery.validate'], exports: '$.validator.unobtrusive' } } }); require(['app/index'], function (app) { app.init(); });
baseUrl , JS-. , . , , require.js. path «» , .

AMD, define . , . , RequireJS . shim , deps () exports ( ).

Text
RequireJS JS-, , , HTML, text .

// app/views/module.html <h3>Module:</h3> <h2>"{name}" is loaded</h2> // module.js define(function (require) { var view = require('text!app/views/module.html'); var name = 'First Module'; return { getHTML: function () { return view.replace('{name}', name); }, getName: function () { return name; } }; });

require module.html , HTML- . , HTML- JS-.


, , production. r.js, require.js.

JS, node.js. , . app.build.js, JS- .

// app.build.js ({ baseUrl: ".", dir: '../Scripts-build', mainConfigFile: 'main.js', name: "main", preserveLicenseComments: false, wrapShim: true })
baseUrl , . dir β€” . main β€” , RequireJS. preserveLicenseComments β€” , wrapShim β€” shim- define . : example.build.js .

>node r.js -o app.build.js

, , pre-build event Visual Studio, JS- , .

Profit
, , RequireJS:

, HTML- debug-

HTML- . JS- .

<!DOCTYPE html> <html> <head> <script data-main="./main" src="lib/require.js"></script> </head> <body> <h1>RequireJS Example</h1> <form> <input /> </form> </body> </html>

data-main main.js ( .js RequireJS ) JS- .

RequireJS , , requirejs.config .

// main.js requirejs.config({ baseUrl: 'Scripts', paths: { jquery: 'jquery-1.11.2', modules: 'app/modules', utils: 'app/utils' }, shim: { 'jquery.validate.unobtrusive': { deps: ['jquery', 'jquery.validate'], exports: '$.validator.unobtrusive' } } }); require(['app/index'], function (app) { app.init(); });
baseUrl , JS-. , . , , require.js. path «» , .

AMD, define . , . , RequireJS . shim , deps () exports ( ).

Text
RequireJS JS-, , , HTML, text .

// app/views/module.html <h3>Module:</h3> <h2>"{name}" is loaded</h2> // module.js define(function (require) { var view = require('text!app/views/module.html'); var name = 'First Module'; return { getHTML: function () { return view.replace('{name}', name); }, getName: function () { return name; } }; });

require module.html , HTML- . , HTML- JS-.


, , production. r.js, require.js.

JS, node.js. , . app.build.js, JS- .

// app.build.js ({ baseUrl: ".", dir: '../Scripts-build', mainConfigFile: 'main.js', name: "main", preserveLicenseComments: false, wrapShim: true })
baseUrl , . dir β€” . main β€” , RequireJS. preserveLicenseComments β€” , wrapShim β€” shim- define . : example.build.js .

>node r.js -o app.build.js

, , pre-build event Visual Studio, JS- , .

Profit
, , RequireJS:

, HTML- debug-
   HTML- .     JS-  . 

<!DOCTYPE html> <html> <head> <script data-main="./main" src="lib/require.js"></script> </head> <body> <h1>RequireJS Example</h1> <form> <input /> </form> </body> </html>

data-main main.js ( .js RequireJS ) JS- .

RequireJS , , requirejs.config .

// main.js requirejs.config({ baseUrl: 'Scripts', paths: { jquery: 'jquery-1.11.2', modules: 'app/modules', utils: 'app/utils' }, shim: { 'jquery.validate.unobtrusive': { deps: ['jquery', 'jquery.validate'], exports: '$.validator.unobtrusive' } } }); require(['app/index'], function (app) { app.init(); });
baseUrl , JS-. , . , , require.js. path «» , .

AMD, define . , . , RequireJS . shim , deps () exports ( ).

Text
RequireJS JS-, , , HTML, text .

// app/views/module.html <h3>Module:</h3> <h2>"{name}" is loaded</h2> // module.js define(function (require) { var view = require('text!app/views/module.html'); var name = 'First Module'; return { getHTML: function () { return view.replace('{name}', name); }, getName: function () { return name; } }; });

require module.html , HTML- . , HTML- JS-.


, , production. r.js, require.js.

JS, node.js. , . app.build.js, JS- .

// app.build.js ({ baseUrl: ".", dir: '../Scripts-build', mainConfigFile: 'main.js', name: "main", preserveLicenseComments: false, wrapShim: true })
baseUrl , . dir β€” . main β€” , RequireJS. preserveLicenseComments β€” , wrapShim β€” shim- define . : example.build.js .

>node r.js -o app.build.js

, , pre-build event Visual Studio, JS- , .

Profit
, , RequireJS:

, HTML- debug-
HTML- . JS- .

<!DOCTYPE html> <html> <head> <script data-main="./main" src="lib/require.js"></script> </head> <body> <h1>RequireJS Example</h1> <form> <input /> </form> </body> </html>

data-main main.js ( .js RequireJS ) JS- .

RequireJS , , requirejs.config .

// main.js requirejs.config({ baseUrl: 'Scripts', paths: { jquery: 'jquery-1.11.2', modules: 'app/modules', utils: 'app/utils' }, shim: { 'jquery.validate.unobtrusive': { deps: ['jquery', 'jquery.validate'], exports: '$.validator.unobtrusive' } } }); require(['app/index'], function (app) { app.init(); });
baseUrl , JS-. , . , , require.js. path «» , .

AMD, define . , . , RequireJS . shim , deps () exports ( ).

Text
RequireJS JS-, , , HTML, text .

// app/views/module.html <h3>Module:</h3> <h2>"{name}" is loaded</h2> // module.js define(function (require) { var view = require('text!app/views/module.html'); var name = 'First Module'; return { getHTML: function () { return view.replace('{name}', name); }, getName: function () { return name; } }; });

require module.html , HTML- . , HTML- JS-.


, , production. r.js, require.js.

JS, node.js. , . app.build.js, JS- .

// app.build.js ({ baseUrl: ".", dir: '../Scripts-build', mainConfigFile: 'main.js', name: "main", preserveLicenseComments: false, wrapShim: true })
baseUrl , . dir β€” . main β€” , RequireJS. preserveLicenseComments β€” , wrapShim β€” shim- define . : example.build.js .

>node r.js -o app.build.js

, , pre-build event Visual Studio, JS- , .

Profit
, , RequireJS:

, HTML- debug-

HTML- . JS- .

<!DOCTYPE html> <html> <head> <script data-main="./main" src="lib/require.js"></script> </head> <body> <h1>RequireJS Example</h1> <form> <input /> </form> </body> </html>

data-main main.js ( .js RequireJS ) JS- .

RequireJS , , requirejs.config .

// main.js requirejs.config({ baseUrl: 'Scripts', paths: { jquery: 'jquery-1.11.2', modules: 'app/modules', utils: 'app/utils' }, shim: { 'jquery.validate.unobtrusive': { deps: ['jquery', 'jquery.validate'], exports: '$.validator.unobtrusive' } } }); require(['app/index'], function (app) { app.init(); });
baseUrl , JS-. , . , , require.js. path «» , .

AMD, define . , . , RequireJS . shim , deps () exports ( ).

Text
RequireJS JS-, , , HTML, text .

// app/views/module.html <h3>Module:</h3> <h2>"{name}" is loaded</h2> // module.js define(function (require) { var view = require('text!app/views/module.html'); var name = 'First Module'; return { getHTML: function () { return view.replace('{name}', name); }, getName: function () { return name; } }; });

require module.html , HTML- . , HTML- JS-.


, , production. r.js, require.js.

JS, node.js. , . app.build.js, JS- .

// app.build.js ({ baseUrl: ".", dir: '../Scripts-build', mainConfigFile: 'main.js', name: "main", preserveLicenseComments: false, wrapShim: true })
baseUrl , . dir β€” . main β€” , RequireJS. preserveLicenseComments β€” , wrapShim β€” shim- define . : example.build.js .

>node r.js -o app.build.js

, , pre-build event Visual Studio, JS- , .

Profit
, , RequireJS:

, HTML- debug-

HTML- . JS- .

<!DOCTYPE html> <html> <head> <script data-main="./main" src="lib/require.js"></script> </head> <body> <h1>RequireJS Example</h1> <form> <input /> </form> </body> </html>

data-main main.js ( .js RequireJS ) JS- .

RequireJS , , requirejs.config .

// main.js requirejs.config({ baseUrl: 'Scripts', paths: { jquery: 'jquery-1.11.2', modules: 'app/modules', utils: 'app/utils' }, shim: { 'jquery.validate.unobtrusive': { deps: ['jquery', 'jquery.validate'], exports: '$.validator.unobtrusive' } } }); require(['app/index'], function (app) { app.init(); });
baseUrl , JS-. , . , , require.js. path «» , .

AMD, define . , . , RequireJS . shim , deps () exports ( ).

Text
RequireJS JS-, , , HTML, text .

// app/views/module.html <h3>Module:</h3> <h2>"{name}" is loaded</h2> // module.js define(function (require) { var view = require('text!app/views/module.html'); var name = 'First Module'; return { getHTML: function () { return view.replace('{name}', name); }, getName: function () { return name; } }; });

require module.html , HTML- . , HTML- JS-.


, , production. r.js, require.js.

JS, node.js. , . app.build.js, JS- .

// app.build.js ({ baseUrl: ".", dir: '../Scripts-build', mainConfigFile: 'main.js', name: "main", preserveLicenseComments: false, wrapShim: true })
baseUrl , . dir β€” . main β€” , RequireJS. preserveLicenseComments β€” , wrapShim β€” shim- define . : example.build.js .

>node r.js -o app.build.js

, , pre-build event Visual Studio, JS- , .

Profit
, , RequireJS:

, HTML- debug-

Source: https://habr.com/ru/post/261141/


All Articles