Эволюция модульности Javascript

Node.js внешний интерфейс JavaScript Ruby

ES2015 был официально выпущен в июне 2015 года, и официальный официально представил нативную поддержку модулей.Сегодня модульная разработка JS очень удобна и естественна, но эта новая спецификация просуществовала всего 3 года. Всего 7 лет назад модульность JS все еще поддерживалась во время выполнения; 13 лет назад зависимости модулей определялись с помощью определений и аннотаций внутренних шаблонов. Для тех, кто это испытал, модульный путь истории до сих пор в памяти и не может быть забыт надолго.

Зачем нужна модульность

Модуль — это программа или подпрограмма, необходимая для выполнения функции. Модули — это «единичные» и «заменяемые» части системы. Так называемая модуляризация относится к системному коду, разделенному на ряд модулей с единой ответственностью и сменными модулями. Модульная разработка относится к тому, как разрабатывать новые модули и повторно использовать существующие модули для реализации функций приложения.

Итак, почему модульный? Основными причинами являются следующие аспекты:

  • Традиционная веб-разработка превращается в разработку веб-приложений
  • Сложность кода постепенно увеличивается.С расширением веб-возможностей все больше и больше бизнес-логики и взаимодействий реализуется на веб-уровне.
  • Разработчики хотят разделить файлы/модули JS, чтобы упростить сопровождение последующего кода.
  • При развертывании вы хотите оптимизировать свой код в несколько HTTP-запросов.

Эволюция модульности

Непосредственно определить зависимости (1999 г.)

Первая попытка внедрить модульность в JS была предпринята в 1999 году под названием «непосредственно определенные зависимости». Этот способ добиться модульности прост и груб — определять и ссылаться на модули через глобальные методы. Dojo использует этот метод для организации модулей, используяdojo.provideопределить модуль,dojo.requireдля вызова модулей, определенных в другом месте.

Мы модифицируем следующий пример в dojo 1.6:

// greeting.js 文件
dojo.provide("app.greeting");

app.greeting.helloInLang = {
    en: 'Hello world!',
    es: '¡Hola mundo!',
    ru: 'Привет мир!'
};

app.greeting.sayHello = function (lang) {
    return app.greeting.helloInLang[lang];
};

// hello.js 文件
dojo.provide("app.hello");

dojo.require('app.greeting');

app.hello = function(x) {
    document.write(app.greeting.sayHello('es'));
};

Способ прямого определения зависимостей очень похож на commonjs, разница в том, что он может определять модули в любом файле, а модули не связаны с файлами. В commonjs каждый файл является модулем.

режим пространства имен (2002 г.)

Сначала мы написали такой код:

function foo() {

}

function bar() {

}

Многие переменные и функции объявляются непосредственно в глобальной глобальной области видимости, которая подвержена конфликтам имен. Таким образом, был предложен шаблон пространства имен. Например:


var app = {};

app.foo = function() {

}

app.bar = function() {

}

app.foo();

Шаблон IIFE анонимных замыканий (2003 г.)

Хотя режим пространства имен в определенной степени решает проблему загрязнения переменных в глобальном пространстве имен, он не может решить проблему изоляции кода и данных.

Пионером в решении этой проблемы является шаблон Anonymous Closure IIFE. Его основная идея заключается в инкапсуляции данных и кода и доступе к ним с помощью внешних методов. Основной пример выглядит следующим образом:


var greeting = (function () {
    var module = {};

    var helloInLang = {
        en: 'Hello world!',
        es: '¡Hola mundo!',
        ru: 'Привет мир!'
    };

    module.getHello = function (lang) {
        return helloInLang[lang];
    };

    module.writeHello = function (lang) {
        document.write(module.getHello(lang))
    };
    
    return module;
}());

Определение зависимости шаблона (2006 г.)

Определение зависимостей шаблона — это следующее решение проблемы модуляризации, которое необходимо использовать вместе с внутренним синтаксисом шаблона для агрегирования файлов js через внутренний синтаксис для достижения загрузки зависимостей.

Первоначально он был реализован в библиотеке Prototype 1.4. В 2005 году,Sam StephensonНачал разработку библиотеки Prototype, которая тогда была частью Ruby on rails. Поскольку Сэм много использует Ruby, неудивительно, что он решил использовать шаблон erb в Ruby в качестве управления зависимостями модулей JS.

Конкретный метод определения зависимости шаблона: для JS-файла, если он зависит от других JS-файлов, он указывается специальным синтаксисом тега в заголовке этого файла. Эти синтаксисы тегов могут быть проанализированы шаблонами бэкенда (erb, jinjia, smarty) и распознаны специальными инструментами сборки, такими как borshik. Следует только упомянуть, что этот режим может работать только напредварительно скомпилированосцена.

Вот пример использования боршика:


// app.tmp.js 文件

/*borschik:include:../lib/main.js*/

/*borschik:include:../lib/helloInLang.js*/

/*borschik:include:../lib/writeHello.js*/

// main.js 文件
var app = {};

// helloInLang.js 文件
app.helloInLang = {
    en: 'Hello world!',
    es: '¡Hola mundo!',
    ru: 'Привет мир!'
};

// writeHello.js 文件
app.writeHello = function (lang) {
    document.write(app.helloInLang[lang]);
};

Аннотация определяет зависимости (2006 г.)

Зависимости, определяемые аннотациями, очень похожи на метод прямого определения зависимостей 1999 г. Разница в том, что зависимости, определяемые аннотациями, определяются в файловых единицах. Зависимости между модулями определяются с помощью синтаксиса аннотаций.

Если приложение хочет использовать этот метод, его можно предварительно скомпилировать (Mootools) или динамически анализировать загруженный код во время выполнения (LazyJS).

// helloInLang.js 文件
var helloInLang = {
    en: 'Hello world!',
    es: '¡Hola mundo!',
    ru: 'Привет мир!'
};

// sayHello.js 文件

/*! lazy require scripts/app/helloInLang.js */

function sayHello(lang) {
    return helloInLang[lang];
}

// hello.js 文件

/*! lazy require scripts/app/sayHello.js */

document.write(sayHello('en'));

Внедрение зависимостей (2009)

В 2004 году Мартин Фаулер предложил концепцию внедрения зависимостей, чтобы описать проблему связи между компонентами в Java.

Пять лет спустя бывшие сотрудники Sun и AdobeMiško Hevery(JAVA-программист) начал разрабатывать JS-фреймворк для своего стартапа, который в основном использует идею внедрения зависимостей, но решает проблему связи между компонентами. Как всем известно, его проект был приобретен Google, и Angular стал одним из самых популярных JS-фреймворков.

// greeting.js 文件
angular.module('greeter', [])
    .value('greeting', {
        helloInLang: {
            en: 'Hello world!',
            es: '¡Hola mundo!',
            ru: 'Привет мир!'
        },

        sayHello: function(lang) {
            return this.helloInLang[lang];
        }
    });

// app.js 文件
angular.module('app', ['greeter'])
    .controller('GreetingController', ['$scope', 'greeting', function($scope, greeting) {
        $scope.phrase = greeting.sayHello('en');
    }]);

Шаблоны CommonJS (2009 г.)

В 2009 году была представлена ​​спецификация CommonJS (или CJS), которая, наконец, реализована в Node.js.

// greeting.js 文件
var helloInLang = {
    en: 'Hello world!',
    es: '¡Hola mundo!',
    ru: 'Привет мир!'
};

var sayHello = function (lang) {
    return helloInLang[lang];
}

module.exports.sayHello = sayHello;

// hello.js 文件
var sayHello = require('./lib/greeting').sayHello;
var phrase = sayHello('en');

console.log(phrase);

Здесь мы обнаруживаем, что для реализации спецификации CommonJS нам нужны две новые записи:requireа такжеmodule, они предоставляют возможность загружать модули и открывать интерфейсы для внешнего мира.

Стоит отметить, что и require, и module являются ключевыми словами языка. В Node.js, поскольку это функция доступности, мы можем ее использовать. Перед отправкой модуля в Node.js на V8 он будет обернут следующей функцией:

(function (exports, require, module, __filename, __dirname) {
    // ...
    // 模块的代码在这里
    // ...
});

Спецификация CommonJS на сегодняшний день является наиболее распространенной спецификацией формата модуля. Вы можете использовать его не только в Node.js, но и в браузере с помощью Browserfiy или Webpack.

Режим AMD (2009)

Работа над CommonJS кипит, а заодно и про асинхронную загрузку модулейОбсуждатьТакже все больше и больше. Основная цель — решить динамические зависимости загрузки веб-приложений, что меньше, чем у CommonJS.

// lib/greeting.js 文件
define(function() {
    var helloInLang = {
        en: 'Hello world!',
        es: '¡Hola mundo!',
        ru: 'Привет мир!'
    };

    return {
        sayHello: function (lang) {
            return helloInLang[lang];
        }
    };
});

// hello.js 文件
define(['./lib/greeting'], function(greeting) {
    var phrase = greeting.sayHello('en');
    document.write(phrase);
});

Хотя модель AMD очень подходит для разработки на стороне браузера, по мере того, как механизм управления пакетами npm становится все более и более популярным, от этого метода постепенно отказываются.

ES2015 Modules(2015)

Модули ES2015 (сокращенно ES-модули) — это модульное решение, которое мы сейчас используем. Оно изначально поддерживается в Node.js 9. Вы можете добавить флаги, запустив--experimental-modulesИспользуйте, не нужно полагаться на такие инструменты, как babel. Он еще не был реализован браузерами, и интерфейсные проекты можно испытать заранее, используя babel или машинописный текст.

// lib/greeting.js 文件
const helloInLang = {
    en: 'Hello world!',
    es: '¡Hola mundo!',
    ru: 'Привет мир!'
};

export const greeting = {
    sayHello: function (lang) {
        return helloInLang[lang];
    }
};

// hello.js 文件
import { greeting } from "./lib/greeting";
const phrase = greeting.sayHello("en");
document.write(phrase);

Суммировать

Эволюция модуляризации JS вызывает у людей эмоции. Благодаря поддержке TC 39 модулей ES процесс модульности JS может наконец подойти к концу. Я надеюсь, что через несколько лет все основные браузеры смогут изначально поддерживать модули ES.

С другой стороны, эволюция модульности JS также показывает, что возможности Интернета постоянно увеличиваются, а веб-приложения становятся все более и более сложными. Я считаю, что в будущем возможности JS будут улучшаться, а эффективность нашей разработки будет более эффективной.


Технологический еженедельник IVWEBШок в сети, обратите внимание на публичный номер: сообщество IVWEB, регулярно каждую неделю публикуйте качественные статьи.