Точка входа в javascript

Инициализация приложения — JS: Архитектура фронтенда

Работу любого приложения можно условно разделить на три стадии, через которые оно проходит в процессе жизни:

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

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

Что входит в инициализацию? Все, что нужно сделать ровно один раз для последующего использования в приложении:

  • Создание начального состояния
  • Настройка i18next
  • Загрузка и запуск фреймворка, если он есть
  • Подключение и настройка различных библиотек: http-клиенты, вебсокеты, работа с датами и так далее

Этот список далеко не полный, в каждой конкретной ситуации в инициализацию попадает что-то свое.

На практике процесс инициализации организуется так: создается функция, внутри которой выполняется вся необходимая настройка. Для удобства сделать это можно в файле init.js.

// Гипотетический пример // файл init.js import i18next from 'i18next'; import io from 'socket.io-client'; // Начальная функция export default async () =>  // создание экземпляра i18next const i18nextInstance = i18next.createInstance(); await i18nextInstance.init( lng: 'ru', resources: /* переводы */ >); const state =  /* описание состояния */ > // создание сокета const socket = new io(); socket.on(/* настройка вебсокетов */); const form = document.querySelector('some-form'); form.addEventListener('submit', (e) =>  // А вот тут логика приложения, ее можно вынести в отдельную функцию или несколько функций в отдельном модуле // где-то в таких обработчиках используется state и socket >); >; 

Запуск этой функции происходит уже в другом месте, например, в файле index.js, который является точкой входа в приложение:

import runApp from './init.js'; runApp(); 

Почему разделение именно такое? Во фронтенде приложение, как правило, глобально. То есть оно одно на всю страницу, грузится ровно один раз и один раз запускается и управляет всем происходящим так, как будто вокруг больше ничего нет (других приложений о которых нужно думать). Но так бывает не всегда. Например, виджеты могут появляться на одной странице более одного раза, а значит каждый виджет должен быть вещью «в себе». То есть инициализация такого виджета работает в своем собственном окружении со своими собственными объектами и не меняет ничего вне (глобальные объекты). Иначе возникнут конфликты и один виджет будет мешать другому.

С другой стороны, в тестировании каждый тест строится так, что он не зависит от других тестов, то есть каждый тест работает так, как будто других тестов не существует. Такое поведение требует инициализации приложения для каждого теста «с нуля». Только в этом случае можно гарантировать, что изменения состояния приложения, сделанные в одном тесте не повлияют на другие тесты. Яркий пример — инициализация i18next. Эта библиотека экспортирует глобальный объект, который можно инициализировать только один раз, повторные инициализации того же объекта (например, при повторных запусках приложения в тестах) приведут к багам и запрещены документацией. По этой причине в примере выше каждый старт приложения создает свой собственный экземпляр i18next, который затем прокидывается в использующие его функции.

// Подробно тесты изучаются в других курсах // Где-то в тестах import runApp from '../src/init.js'; // Эта функция выполняется перед каждым тестом beforeEach(() =>  runApp(); // инициализация >); test(/* тут тесты */) test(/* тут тесты */) 

Открыть доступ

Курсы программирования для новичков и опытных разработчиков. Начните обучение бесплатно

Источник

Ввод и контекст

Объект входа-это то место,где webpack ищет,чтобы начать сборку пакета.Контекст-это абсолютная строка к каталогу,в котором находятся файлы для записи.

context

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

const path = require('path'); module.exports = < //. context: path.resolve(__dirname, 'app'), >;

По умолчанию используется текущий рабочий каталог Node.js,но рекомендуется передать значение в вашей конфигурации.Это делает вашу конфигурацию независимой от CWD (текущий рабочий каталог).

entry

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

Динамически загружаемый модуль не является точкой входа.

Правило,которое следует учитывать:одна точка входа на HTML-страницу.SPA:одна точка входа,MPA:несколько точек входа.

module.exports = < //. entry: < home: './home.js', about: './about.js', contact: './contact.js', >, >;

Naming

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

Entry descriptor

Если передается объект,то значением может быть строка,массив строк или дескриптор:

module.exports = < //. entry: < home: './home.js', shared: ['react', 'react-dom', 'redux', 'react-redux'], catalog: < import: './catalog.js', filename: 'pages/catalog.js', dependOn: 'shared', chunkLoading: false, // Отключаем блоки, которые загружаются по запросу, и помещаем все в основной блок. >, personal: < import: './personal.js', filename: 'pages/personal.js', dependOn: 'shared', chunkLoading: 'jsonp', asyncChunks: true, // Создаем асинхронные блоки, которые загружаются по запросу. layer: 'name of layer', // устанавливаем слой для точки входа >, >, >;

Синтаксис дескриптора может быть использован для передачи дополнительных опций точке входа.

Output filename

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

module.exports = < //. entry: < app: './app.js', home: < import: './contact.js', filename: 'pages/[name][ext]' >, about: < import: './about.js', filename: 'pages/[name][ext]' >, >, >;

Здесь использовался синтаксис дескриптора для передачи опции filename в определенные точки входа.

Dependencies

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

module.exports = < //. entry: < app: < import: './app.js', dependOn: 'react-vendors' >, 'react-vendors': ['react', 'react-dom', 'prop-types'], >, >;

app кусок не будет содержать модули , которые react-vendors имеют.

dependOn также может принимать массив строк:

module.exports = < //. entry: < moment: < import: 'moment-mini', runtime: 'runtime' >, reactvendors: < import: ['react', 'react-dom'], runtime: 'runtime' >, testapp: < import: './wwwroot/component/TestApp.tsx', dependOn: ['reactvendors', 'moment'], >, >, >;

Кроме того,вы можете указать несколько файлов в одной записи,используя массив:

module.exports = < //. entry: < app: < import: ['./app.js', './app2.js'], dependOn: 'react-vendors' >, 'react-vendors': ['react', 'react-dom', 'prop-types'], >, >;

Dynamic entry

Если функция передана, она будет вызываться при каждом событии make .

Обратите внимание, что событие make срабатывает при запуске webpack и при каждой недействительности при отслеживании изменений файлов .

module.exports = < //. entry: () => './demo', >;
module.exports = < //. entry: () => new Promise((resolve) => resolve(['./demo', './demo2'])), >;

Например:вы можете использовать динамические записи для получения фактических записей из внешнего источника (удаленного сервера,содержимого файловой системы или базы данных):

webpack.config.js

module.exports = < entry( ) < return fetchPathsFromSomeExternalSource(); // возвращает обещание, которое будет разрешено чем-то вроде ['src / main-layout.js', 'src / admin-layout.js'] >, >;

При объединении с опцией output.library : Если передается массив, экспортируется только последний элемент.

webpack 5.75

‘auto’ номер строки Укажите номер порта для прослушивания запросов: webpack.config.js Использование через интерфейс командной строки: параметр порта не может быть нулевой пустой строкой, автоматически

boolean:false Опция экспериментов была введена webpack 5,чтобы дать пользователям возможность активировать и опробовать экспериментальные функции.

Источник

Разбираем Node.js. Как свойство main в package.json определяет точку входа

Разбираем Node.js. Как свойство main в package.json определяет точку входа главное изображение

При загрузке зависимости Node.js работает в два этапа. Это достаточно сильно отличается от загрузки модулей, встроенных в Node.js, например, с помощью require(‘fs’) или локального модуля с помощью require (‘./queue/mem.js’) . Зависимость загружается в два основных этапа:

Поиск директории

Среда выполнения анализирует все директории, которые находятся на пути от текущего файла к корню файловой системы. В каждой директории Node.js проверяет, содержит ли она папку node_modules . В случае, если поиск заканчивается успехом, среда выполнения переходит внутрь этой директории и ищет внутри поддиректорию, имя которой должно соответствовать имени загружаемого модуля. То есть, если мы импортируем lodash — require(‘lodash’) , то Node.js будет искать директорию node_modules/lodash . Node.js будет это делать, пока не найдет совпадение.

Поиск точки входа

Найдя нужную директорию, Node.js попробует несколько стратегий для определения точки входа. Точкой входа является файл, module.exports которого возвращается в качестве значения вызова функции require() .

Сначала Node.js ищет package.json файл и проверяет, содержит ли он свойство main . Оно будет использоваться для указания на файл внутри директории пакета, который и будет точкой входа. Если main не существует, то Node.js будет пытаться загрузить файлы в следующем порядке — index.js, index.json, index.node.

— Если package.json содержит свойство main ;

— Если свойства main нет, то Node будет загружать по порядку — index.js, index.json, index.node .

Как выглядит точка входа для популярных пакетов

То, что происходит внутри пакетов, зависит от их авторов. Есть несколько способов указать точку входа в определенный пакет. Вот так это делают некоторые популярные модули npm.

Main

При этом многие пакеты определяют свойство main , и только некоторые оставляют его для поиска по умолчанию.

Адаптированный перевод статьи Main property in package.json defines package entry point с сайта Byte Archer by Panu Pitkamaki. Мнение администрации Хекслета может не совпадать с мнением автора оригинальной публикации.

Источник

Читайте также:  Javascript вывести таблицу умножения
Оцените статью