Загробная жизнь модульного управления Javascript

внешний интерфейс JavaScript Webpack RequireJS

Загробная жизнь модульного управления Javascript

[TOC]

На самом деле, концепция управления модулями упоминалась с тех пор, как несколько лет назад фронтенд пережил эру резки и сжигания, поэтому мы подумали о том, к чему конкретно относится это управление модулями? Что за презентация? Историческое происхождение? Какое сейчас состояние?

Что я прямо вспоминаю, так это впечатление от управления cmd и commonJS этими тремя модулями. Но знаете ли вы, почему появляется cmd и commonJS? Далее давайте посмотрим, что это такое.

Я чувствую, что у меня разное понимание одной и той же технологии на каждом этапе.

1. Что такое модульная разработка

Для того, чтобы огромный проект выглядел аккуратно и аккуратно, в нашей повседневной разработке постепенно появляются три общие модульные библиотеки управления: requireJS, seaJS, спецификация commonJS (обратите внимание, что commonJS здесь не библиотека, а норма). Некоторые инструменты сборки, которые зависели от этих трех типов спецификаций, появились одновременно, но в итоге все они проиграли вебпаку. Это статья, которая знакомит с основами webpack, которые можно интерпретировать вместе с этой статьей.Создание приложения из веб-пакета 4.0+ "Дорога к интерфейсу"

1-1.Первый этап модуляризации

На этом этапе мы часто инкапсулируем множество сложных функций в функции:

function f1() {
	// todo
}

function f2() {
	// todo
}
.
.
.

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

1-2.Инкапсуляция в объекты

На втором этапе, чтобы избежать загрязнения глобальных переменных, мы инкапсулируем один модуль в объект. следующим образом:


const module = {
	_number: 10,
	f1: () => { 
		console.log(123)
	},
	f2: () => { 
		console.log(456)
	},
	.
	.
	.
}

Таким образом, у нас нет модуля для определения объекта, просто вызовите его напрямую, когда это необходимо, но это также будет проблемой. Запись таким образом выставит все свойства внутри объекта,内部状态可以被外部改变Например:

module._number = 100

Если мы заплатим соответствующие модули, чтобы написать так. Мы произвольно меняем сумму платежа, поэтому будет более опасная ситуация.

1-3.Оптимизация объекта

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

const module2 = (function() {
	let _money = 100
	const m1 = () => {
		console.log(123)
	}
	const m2 = () => {
		console.log(456)
	}
	return {
		f1: m1,
		f2: m2
	}
})()

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

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

Во-вторых, процесс разработки модульного управления

2-1. CommonJS

Отправная точка CommonJS: JS не имеет полной модульной системы, имеет меньше стандартных библиотек и не имеет инструментов управления пакетами. (Хотя в эти штуки уже давно играют на бекенде и играть не хотят) С появлением NodeJS JS можно запускать где угодно, особенно на стороне сервера, так что фоновые языки, такие как Java, C# и PHP, имеют возможность разрабатывать крупномасштабные приложения, поэтому появился CommonJS.

2-1-1, общие нормы CommonJS

  • Файл — это модуль с отдельной областью действия.
  • К этому модулю относятся переменные, функции и объекты, определенные обычным образом.
  • пройти черезrequireзагрузить модуль
  • пройти черезexportsа такжеmodule.exportsвыставить содержимое модуля

Мы пытаемся написать эту спецификацию, написав демо

Демонстрация 1: Экспорт модулей через module.exports

// module.js
module.exports = {
  name: "zhang",
  getName: function() {
    console.log(this.name);
  },
  changeName: function(n) {
    this.name = n;
  }
};

// index.js
const module = require("./module/index");
console.log(module)	//  {name: "zhang", getName: ƒ, changeName: ƒ} "commons"

Демонстрация 2: Экспорт модулей через экспорт

// module1.js
const getParam = () => {
  console.log(a);
};
let a = 123;
let b = 456;

exports.a = a;
exports.b = b;
exports.getParam = getParam;

// index.js
const module1 = require("./module/index1");
consoel.log(module1, "commons1")	// {a: 123, b: 456, getParam: ƒ} "commons1"

Демонстрация 3: для экспорта модулей существуют как exports, так и module.exports.

// module2.js
let a = 123;

const getSome = () => {
  console.log("yyy");
};

const getA = () => {
  console.log(a);
};

exports.getSome = getSome;
module.exports = getA;

// index.js
const module2 = require("./module/index2");
consoel.log(module2, "commons2")	// function getA() {...}

Резюме: На таком сравнительном примере можно наглядно сравнить разницу между exports и module.exports: 1. Если экспорт и модуль.экспорт существуют одновременно, модуль.экспорт перезапишет экспорт. 2. Когда внутри модуля все экспорты, это эквивалентно module.exports 3. Наконец, мы можем заключить, что экспорты на самом деле являются подмножеством module.exports.

Вышеизложенное является нашим основным введением в CommonJS. Также есть жесткая спецификация, здесь мы просто перечисляем ее, а не делаем детальную демо-демонстрацию.

2-1-2, спецификация CommonJS --- загрузка, область действия

Весь код выполняется в области модуля и не загрязняет глобальную область; модуль может быть загружен несколько раз, но он будет запущен только один раз, когда он загружается в первый раз, а затем результат выполнения будет кэшироваться, а когда он загружается позже, он будет прочитан напрямую Возьмем кешированный результат, порядок загрузки модулей синхронно загружается в соответствии с порядком появления кода;

2-1-3, спецификация CommonJS --- __имя_каталога, __имя_файла

__dirname представляет собой путь к папке, в которой находится текущий файл модуля, а __filename представляет собой путь к папке + имя файла, в котором находится текущий файл модуля;

Вышеприведенное является введением в спецификацию CommonJS.Для получения более подробной документации вы можете обратиться к официальной документации по спецификации CommonJS.

2-2.Импорт-экспорт CommonJS и ES6 (ES2015)

До выхода стандарта ES2015 наиболее важными были спецификации CommonJS и AMD. Выше мы уже представили спецификацию CommonJS (в основном для службы NodeJS на стороне сервера), поэтому, когда появится стандарт ES6, он станет очень хорошим дополнением к модуляризации на стороне браузера.

Здесь мы по-прежнему более подробно расскажем о функциях импорта-экспорта ES6.

2-2-1, экспорт ES6

экспорт — это интерфейс, используемый для экспорта переменных этого модуля (файл может пониматься как модуль) во внешнюю среду.

Demo 1 export { xxx }

// export/index.js
const a = "123";
const fn = () => window.location.href;

export { fn };

// show/index.js
const ex = require("./export/index");
import x from "./export/index";
import { fn } from "./export/index";
console.log(ex, "export1"); // {fn: ƒ, __esModule: true} "export1"
console.log(x, "export-x"); // undefined "export-x"
console.log(fn, "export-fn"); // function() { return window.location.href; } "export-x"

Demo 2 export default xxx

// export/index1.js
const a = "123";
const fn = () => window.location.href;
export default fn;


// show/index1.js
const ex1 = require("./export/index1");
import x from "./export/index1";

console.log(ex1, "export1"); 
// {default: ƒ, __esModule: true} "export1"
console.log(x, "export2"); 
// ƒ fn() {return window.location.href;} "export2"

С помощью Demo 1 и Demo 2 мы можем сравнить разницу между экспортом и экспортом по умолчанию.

exportЧто можно экспортировать, так это несколько свойств и методов, содержащихся в объекте.export defaultЭкспортировать можно только безымянный объект.

import {fn} from './xxx/xxx'(Эталонный метод экспорта-экспорта)import fn from './xxx/xxx1'(Экспортный метод экспорта по умолчанию)

В то же время мы обнаружили, что можем напрямую использовать require для ссылки

Как-то странно, что это тоже можно процитировать. Но функция такая же, как импорт. (Причина в том, что у меня есть сервер, связанный с веб-пакетом здесь)

2-2-2, импорт ES6

Здесь тот же пример, что и в демо выше.Вывод таков:

import {fn} from './xxx/xxx'(Эталонный метод экспорта-экспорта)import fn from './xxx/xxx1'(Эталонный метод экспорта по умолчанию, вам не нужно заботиться об имени модуля экспортируемого модуля)

Резюме: понятия экспорта и ссылки на модули раньше были довольно волшебными, но на этот раз я, наконец, понял это благодаря знаниям. 😄

Демонстрационный пример портала:Модульный"""

2-3 AMD RequireJS

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


requireJS в основном решает две проблемы:

  • 1. Несколько файлов js могут иметь зависимости, и зависимые файлы должны быть загружены в браузер раньше, чем файлы, которые от них зависят.
  • 2. При загрузке js браузер останавливает отрисовку страницы, чем больше загружено файлов, тем дольше страница теряет время отклика.
  • 3. Асинхронная предварительная загрузка! (Что вы имеете в виду? Мы представим это в основной главе позже)

Давайте представим синтаксис RequireJS через демонстрацию:

// 定义模块
define(['myModule'],() => {
  var name = 'Byron';
  function printName(){
     console.log(name);
}
  return {
     printName:printName
   }
})

// 加载模块
require(['myModule'],function(my){
   my.printName();
})

Синтаксис требуемого JS:

define(id,dependencies,factory)

——idНеобязательный параметр, используемый для определения идентификатора модуля.Если этот параметр не указан, имя файла сценария (с удаленным расширением)

——dependenciesмассив имен модулей, используемых текущим модулем

——factoryФабричный метод, функция или объект, который будет выполняться при инициализации модуля, если это функция, она должна выполняться только один раз, если это объект, этот объект должен быть выходным значением модуля.


Используйте функцию require на странице для загрузки модуля;require([dependencies], function(){}); require()Функция принимает два параметра: - первый параметр数组, указывая на то, что依赖的模块; - Второй параметр - это回调函数,когда前面指定的模块都加载成功后,它将被调用. Загруженные модули будут переданы функции в качестве параметров, чтобы их можно было использовать внутри функции обратного вызова.

2-4, CMD Seajs

define(id, deps, factory)

因为CMD推崇一个文件一个模块,所以经常就用文件名作为模块id;
CMD推崇依赖就近,所以一般不在define的参数中写依赖,而是在factory中写。

factory有三个参数:
function(require, exports, module){}

一,require
require 是 factory 函数的第一个参数,require 是一个方法,接受 模块标识 作为唯一参数,用来获取其他模块提供的接口;

二,exports
exports 是一个对象,用来向外提供模块接口;

三,module
module 是一个对象,上面存储了与当前模块相关联的一些属性和方法。

demo
// 定义模块  myModule.js
define(function(require, exports, module) {
  var $ = require('jquery.js')
  $('div').addClass('active');
});

// 加载模块
seajs.use(['myModule.js'], function(my){

});

2-5 Различия между AMD RequireJS и CMD SeaJS

AMD уважает предварительную зависимость и объявляет модули, от которых она зависит, при определении модуля. CMD учитывает ближайшую зависимость и требует ее только при использовании модуля.


люди говорят:

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

Многие говорят, что requireJS — это модуль асинхронной загрузки, а SeaJS — модуль синхронной загрузки.Это понимание на самом деле неточное.На самом деле модули загрузки асинхронные, но AMD полагается на фронт.js может легко узнать, кто является зависимым модулем. и загрузите его немедленно. И CMD близок к зависимости, вам нужно использовать модуль, чтобы преобразовать модуль в строку, чтобы проанализировать его, чтобы узнать, какие модули зависимы.Это также момент, за который многие люди критикуют CMD, жертвуя производительностью чтобы обеспечить удобство разработки, на самом деле требуется короткое время для анализа модуля, который будет проигнорирован.

3. Принцип модульности каркаса

3-1, принцип реализации

(function(global){
    var modules = {};
    var define = function (id,factory) {
        if(!modules[id]){
            modules[id] = {
                id : id,
                factory : factory
            };
        }
    };
    var require = function (id) {
        var module = modules[id];
        if(!module){
            return;
        }

        if(!module.exports){
            module.exports = {};
            module.factory.call(module.exports,require,module.exports,module);
        }

        return module.exports;
    }

    global.define = define;
    global.require = require;
})(this);

Пример использования:

define('Hello',function(require,exports,module){
    function sayHello() {
        console.log('hello modules');
    }
    module.exports = {
        sayHello : sayHello
    }
});

var Hello = require('Hello');
Hello.sayHello();

4. Резюме

4-1.Почему так?

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

4-2. Почему бы не использовать requirejs, seajs и т. д.

Они мощные, но размер файла является проблемой, плюс бизнес иногда может быть менее сложным.

4-3. Применимые сценарии

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

4-4 Реальность

webpack + commonJS + ES6 (import + export )

Таким образом, может быть реализовано управление модулями и управление более крупными проектами. Что ж, модульное управление представлено здесь первым, добро пожаловать на совместное обсуждение.


Здесь представлена ​​статья о загробной жизни и этой жизни модульного управления интерфейсом Javascript, добро пожаловать на совместное обсуждение Дао~

Адрес GitHub: (добро пожаловать в звезду, добро пожаловать, чтобы порекомендовать:)

Загробная жизнь интерфейсного модульного управления Javascript