Что за файл index js
While components can reside in src/components/my-component-name, it is recommended to have an index.js inside that directory. Thus, whenever someone imports the component using src/components/my-component-name, instead of importing the directory, this would actually import the index.js file.
This index.js file, how should I create it to return the component?
For example I want to create some pages for different routes:
Now, the index.js should look like this?
And there should be no problem with the Router component because all I have to do without index.js is to import MyPage and do something like this:
Is this the correct way to create that index.js file?
Who told you that? There is literally nothing about React that makes this "better" or "preferred". In fact, using index.js for single components is just clutter. If you have an index that allowed you to say const < MyComponent, SecondaryComponent, ChildThing, AndMore >= require('./components/ );`, then sure that's useful, but for individual components this advice makes very little sense. Can you cite you source?
You don't have to, it just lets you control the interface of your modules more easily. And this isn't React-specific, it's general JS.
Your code and your js files are fine; about index.js | ts | html| jsx | tsx it is just the way every product and professional expect it, nothing special; that is the way tools and people have used to and evolved. like the "Hello World" from early programming days
index.js file acts like a container where you render all the subcomponents of the page.This helps you to split the code into smaller chunks which improves readability and testing
First of all, thank you for your time, but I don't think I understand your answer. Ok, it's not a great idea to import a Button component from button.js , I understand this, but what I wanted to emphasize is instead of importing the directory, this would actually import the index.js file -> and my question: is react looking by default for an index.js file when you import the component ??
Использование диспетчера пакетов из JavaScript (npm)
Примерно с 2010-го развиваются несколько конкурирующих диспетчеров пакетов, помогающих автоматизировать скачивание и обновление библиотек из центрального репозитория. Bower был самым популярным в 2013-м, но к 2015-му уступил пальму первенства npm. Надо сказать, что с конца 2016-го yarn широко используется в качестве альтернативы интерфейсу npm, но под капотом он всё ещё работает с npm-пакетами.
Изначально npm создавался как диспетчер пакетов специально для node.js, среды исполнения JavaScript, предназначенной для серверов, а не фронтенда. Так что довольно странно применять его в качестве диспетчера пакетов для библиотек, запускаемых в браузерах.
Примечание: обычно диспетчеры пакетов подразумевают использование командной строки, что раньше никогда не требовалось при разработке фронтенда. Если вы никогда с ней не работали, то для начала можете почитать это руководство. Как бы там ни было, в современном JavaScript важно уметь пользоваться командной строкой (и это также открывает двери в другие области разработки).
Давайте посмотрим, как использовать npm для автоматической установки moment.js вместо скачивания вручную. Если у вас установлен node.js, то у вас уже есть и npm, так что можете в командной строке перейти в папку с файлом index.html и ввести:
Вам зададут несколько вопросов (можно просто жать Enter, оставляя ответы по умолчанию), а потом сгенерируется новый файл package.json. Это конфигурационный файл, в котором npm сохраняет всю информацию о проекте. По умолчанию содержимое package.json выглядит так:
Для установки JS-пакета moment.js можно воспользоваться инструкциями с сайта npm, введя в командной строке:
Эта команда делает две вещи:
- Скачивает весь код из пакета moment.js в папку под названием node_modules.
- Автоматически модифицирует файл package.json для отслеживания moment.js в качестве проектной зависимости.
Это полезно, когда вы станете работать над проектом совместно с другими разработчиками: вместо общего доступа к папке node_modules (которая может быть очень большой) достаточно открыть доступ к файлу package.json, и другие разработчики смогут автоматически устанавливать нужные пакеты с помощью команды npm install .
Теперь нам больше не нужно вручную скачивать moment.js с сайта, npm помогает скачивать и обновлять автоматически. Если посмотрим в папку node_modules, то в директории node_modules/moment/min увидим файл moment.min.js. Это означает, что в index.html можно сослаться на скачанную через npm версию moment.min.js:
Приятно, что теперь мы можем автоматически скачивать и обновлять наши пакеты с помощью npm и командной строки. Но теперь надо копаться в папке node_modules, чтобы узнать местонахождение каждого пакета и вручную прописать в HTML. Это довольно неудобно, так что давайте посмотрим, как можно автоматизировать этот процесс.
Babel модуль: транспиляция ES модуля
Babel — это еще один транспилятор для обеспечения работы ES6+ кода в старых браузерах. Приведенный выше ES6+ модуль может быть преобразован в Babel модуль следуюшим образом:
А вот код в index.js , демонстрирующий использование этого модуля:
Это транспиляция по умолчанию. Babel также умеет работать с другими инструментами.
Babel и SystemJS
SystemJS может использоваться как плагин для Babel:
Данный плагин должен быть добавлен в babel.config.json :
Теперь Babel может работать с SystemJS для транспиляции CommonJS/Node.js, AMD/RequireJS и ES модулей:
Весь синтаксис AMD, CommonJS и ES модулей транспилирован в синтаксис SystemJS:
Webpack модуль: транспиляция и сборка CJS, AMD и ES модулей
Webpack — это сборщик модулей. Его транспилятор объединяет CommonJS, AMD и ES модули в единый сбалансированный модульный шаблон и собирает весь код в один файл. Например, в следующих 3 файлах определяются 3 модуля с помощью различного синтаксиса:
Следующий код демонстрирует использование этого модуля:
Webpack способен объединить эти файлы, несмотря на то, что они представляют собой разные модульные системы, в один файл main.js :
Поскольку Webpack основан на Node.js, он использует модульный синтаксис CommonJS. В webpack.config.js :
Для транспиляции и сборки необходимо выполнить следующие команды:
В результате Webpack создаст файл main.js . Следующий код из main.js отформатирован для улучшения читаемости:
И снова это всего лишь IIFE. Код из 4 файлов преобразован в массив из 4 функций. И этот массив передается анонимной функции в качестве параметра.
3 Answers 3
The index.js file is good to use when you have a lot of components you need to export from a given folder and you would like to destructure in the files you're importing them into. You don't have to follow this at all, but is still best practice to do it this way; it can be easier when exporting a large amount of files such as from a reducer in Redux or a utility folder with a large amount of smaller components like a or , and it is easier to read for other users if everything coalesces into a single index file rather than several different files.
index.js has special properties that if you import from a file, javascript will look for the index.js if nothing else is specified. Either way works but for larger scale applications using the index.js is preferred.
That's the cool part is node will look for the index.js file in a directory if no file is specified. You're question made me realize I could make my answer a little more clear on that front and I've updated it as such.
I read somewhere that import from 'x' affects tree-shaking and that multiple default imports are better, like import A from 'x'; import B from 'x'; . Is this true?
The source you cite is about create-react-app , but the author puts their own opinions on top and presents them as if they're established fact.
By all means, use an index.js if you want implicit imports (there are situations in which it is an excellent idea to do so), but create-react-app doesn't care, it does not "recommend to have an index.js inside that directory", and this article is simply being misleading. There are reasons for adding an index.js , and they are wholly unrelated to create-react-app , React in general, or even the practice of writing JS in class form.
В этом материале мы поговорим о файлах компонентов и о структуре React-проектов.
TypeScript модуль: транспиляция CJS, AMD, ES и SystemJS модулей
TypeScript поддерживает все разновидности синтаксиса JS, включая ES6. При транспиляции синтаксис ES6 модуля может быть сохранен или преобразован в другой формат, в том числе CommonJS/Node.js, AMD/RequireJS, UMD/UmdJS или SystemJS согласно настройкам транспиляции в tsconfig.json :
Модульный синтаксис ES, поддерживаемый TypeScript, получил название внешних модулей.
Внутренние модули и пространство имен
TypeScript также имеет ключевые слова module и namespace . Они называются внутренними модулями:
Оба транспилируются в JS объекты:
TypeScript module и namespace могут иметь несколько уровней вложенности через разделитель . :
Sub module и sub namespace транспилируются в свойства объекта:
TypeScript module и namespace также могут использоваться в операторе export :
Приведенный код также транспилируется в sub module и sub namespace:
Заключение
Мы вкратце рассмотрели современный JavaScript. Прошли от сочетания чистых HTML и JS до использования:
- диспетчера пакетов для автоматической загрузки сторонних пакетов;
- бандлера для создания единых файлов скриптов;
- транспилятора для использования будущих возможностей JS;
- и средства запуска задач для автоматизации разных операций в процессе сборки.
Конечно, здесь много куда можно двигаться, особенно новичкам. Для них веб-разработка раньше была прекрасной отправной точкой, потому что можно было легко начать и втянуться в дело. А сегодня это уже не такое простое занятие, в частности из-за разнообразия быстро сменяющих друг друга инструментов.
Но всё не так плохо, как может показаться. Ситуация устаканивается, node-экосистема всё больше воспринимается как жизнеспособный вариант работы с фронтендом. Удобство и согласованность в работе обеспечивается использованием npm в качестве диспетчера пакетов, node-выражений require или import для работы с модулями и npm-скриптов для запуска задач. И этот рабочий процесс гораздо проще, чем было год-два назад!
Фреймворки сегодня часто поставляются с инструментами, облегчающими начало веб-разработки. В Ember есть ember-cli , оказавший огромное влияние на angular-cli из Angular, create-react-app из React, vue-cli из Vue и т. д. Эти инструменты обеспечат ваш проект всем необходимым для того, чтобы начать писать код. Но они не волшебные палочки, они лишь правильно всё настраивают для комфортной работы. Нередко вам может понадобиться дополнительно настроить конфигурацию webpack, babel и т. д. И очень важно понимать, что делает каждый из инструментов.
С современным JavaScript может быть тяжело работать, потому что он продолжает быстро меняться и развиваться. Но даже если иногда это похоже на изобретение колеса, быстрая эволюция языка помогает продвигать инновации вроде горячей перезагрузки, линтинга в реальном времени и отладки в режиме «машины времени». Сегодня интересно быть разработчиком, и я надеюсь, что эта статья поможет вам спланировать свой собственный путь.
Представляю вашему вниманию перевод статьи «Understanding (all) JavaScript module formats and tools» автора Dixin.
При создании приложения часто возникает желание разделить код на части, логические или функциональные блоки (модули). Однако JavaScript изначально не имел поддержки модулей. Это привело к появлению различных модульных технологий. В настоящей статье обсуждаются все основные понятия, шаблоны, библиотеки, синтаксис и инструменты для работы с модулями в JavaScript.
Заключение
Хотя компоненты могут находиться в src / components / my-component-name, рекомендуется иметь index.js внутри этого каталога. Таким образом, всякий раз, когда кто-то импортирует компонент, используя src / components / my-component-name, вместо импорта каталога, он фактически импортирует файл index.js.
Этот файл index.js, как я должен создать его, чтобы вернуть компонент?
Например, я хочу создать несколько страниц для разных маршрутов:
Теперь index.js должен выглядеть так?
И структура проекта:
И не должно быть никаких проблем с компонентом Router, потому что все, что мне нужно сделать без index.js, это импортировать MyPage и сделать что-то вроде этого:
Это правильный способ создания этого файла index.js?
Системный модуль: SystemJS модуль
SystemJS — это библиотека для обеспечения работы ES модулей в старых браузерах. Например, следующий модуль написан с использованием синтаксиса ES6:
Этот код не будет работать в браузерах, не поддерживающих синтаксис ES6. Одним из решений данной проблемы является транспиляция кода с помощью интерфейса System.register библиотеки SystemJS:
Нового модульного синтаксиса ES6 больше нет. Зато код будет прекрасно работать в старых браузерах. Эта транспиляция может быть выполнена автоматически с помощью Webpack, TypeScript и т.д.
Динамическая загрузка модуля
SystemJS также содержит функцию import для динамического импорта:
Олдскульное использование JavaScript
Давайте сделаем «олдскульный» сайт, используя только HTML и JavaScript. В этом случае придётся вручную скачивать и связывать файлы. Вот простой index.html, ссылающийся на JavaScript-файл:
Строка ссылается на JavaScript-файл index.js, находящийся в той же директории:
Больше для создания сайта ничего не нужно! Допустим, вы хотите добавить стороннюю библиотеку moment.js (меняет формат дат для удобочитаемости). Можно, к примеру, использовать в JS функцию moment :
Но так вы всего лишь добавили moment.js на свой сайт! На главной странице moment.js приведены инструкции:
Мда, в разделе «Установка» много всего написано. Но пока это проигнорируем, потому что можно добавить moment.js на сайт, скачав файл moment.min.js в ту же директорию и включив его в наш файл index.html.
Обратите внимание, что moment.min.js загружается до index.js, поэтому в index.js вы можете использовать функцию moment :
Вот так мы создавали сайты с JS-библиотеками. Процедура была простой для понимания, но раздражала необходимость искать и скачивать новые версии библиотек при каждом их обновлении.
CJS модуль: CommonJS модуль или Node.js модуль
CommonJS, первоначально названный ServerJS, это шаблон для определения и использования модулей. Он встроен в Node.js. По умолчанию каждый JS файл — это CJS. Переменные module и exports обеспечивают экспорт модуля (файла). Функция require обеспечивает загрузку и использование модуля. Следующий код демонстрирует определение модуля счетчика на синтаксисе CommonJS:
Вот как этот модуль используется:
В среде выполнения (движке) Node.js этот шаблон используется путем оборачивания кода внутри файла в функцию, которой в качестве параметров передаются переменные exports, module и функция require :
Использование бандлера (bundler) JavaScript-модулей (webpack)
В большинстве языков программирования есть возможность импортирования кода из одного файла в другой. Изначально в JS такой возможности не было, потому что этот язык разрабатывался только для исполнения в браузере, без доступа к файловой системе на клиентской машине (по причинам безопасности). Так что долгое время для организации JS-кода в нескольких файлах требовалось загружать каждый файл с глобально доступными переменными.
Именно это мы и делали в вышеописанном примере с moment.js example — весь файл moment.min.js загружается в HTML, где определяется глобальная переменная moment, которая потом становится доступна любому файлу, загруженному после moment.min.js (вне зависимости от того, нужна ли она для обращения к ним).
В 2009-м был запущен проект CommonJS, в рамках которого планировалось создать спецификации внебраузерной экосистемы для JavaScript. Большая часть CommonJS была посвящена спецификациям модулей, позволявших JS импортировать и экспортировать код между файлами как во многих других языках, без обращения к глобальным переменным. Самой известной реализацией модулей CommonJS стал node.js.
Как уже говорилось, node.js — это среда исполнения JavaScript, разработанная для запуска на серверах. Вот как сначала выглядело использование node.js-модулей: вместо загрузки всего moment.min.js в скриптовом теге HTML можно было грузить JS-файл напрямую:
Загрузка модулей работает прекрасно, поскольку node.js — это серверный язык с доступом к файловой системе. Также ему известно расположение всех npm-модулей, поэтому вместо require('./node_modules/moment/min/moment.min.js) можно писать просто require('moment') .
Всё это прекрасно, но если вы попробуете использовать приведённый код в браузере, то получите ошибку, в которой говорится, что require не определён. У браузера нет доступа к файловой системе, поэтому такая загрузка модулей реализована очень хитро: файлы нужно грузить динамически, синхронно (замедляет исполнение) или асинхронно (могут быть проблемы с синхронизацией).
И здесь появляется бандлер (bundler). Это инструмент для сборки модулей в единые пакеты, имеющий доступ к файловой системе. Получающиеся пакеты совместимы с браузером, которому не нужен доступ к файловой системе. В нашем случае бандлер нужен для поиска всех выражений require (имеющих ошибочный, с точки зрения браузера, JS-синтаксис) и замены на настоящее содержимое каждого требуемого файла. В финале мы получаем единый JS-файл без выражений require !
Самым популярным бандлером сначала был Browserify, выпущенный в 2011 г. Он был пионером в использовании node.js-выражений require во фронтенде (это позволило npm стать самым востребованным диспетчером пакетов). К 2015-му лидером стал webpack (ему помогла популярность фронтенд-фреймворка React, использующего все возможности этого бандлера).
Давайте посмотрим, как с помощью webpack заставить работать в браузере наш пример с require('moment') . Сначала установим бандлер в проект. Сам по себе webpack — это npm-пакет, так что введём в командной строке:
Обратите внимание на аргумент --save-dev — он сохраняет бандлер как зависимость среды разработки, так что она не понадобится на production-сервере. Это отразится в файле package.json, который обновится автоматически:
Теперь webpack установлен в качестве одного из пакетов в папке node_modules. Можно запускать его из командной строки:
Эта команда запускает webpack вместе с файлом index.js, находит все выражения require и заменяет соответствующим кодом, чтобы получился единый выходной файл bundle.js. Это означает, что нам больше не нужно использовать в браузере файл index.js, поскольку он содержит некорректные выражения require . Вместо него мы возьмём bundle.js, что должно быть учтено в index.html:
Если обновите браузер, то всё будет работать, как и прежде.
Обратите внимание, что нам нужно выполнять webpack-команду при каждом изменении index.js. Это утомительно, и чем более продвинутые возможности webpack мы будем использовать (вроде генерирования схемы источников для отладки исходного кода из транспилированного), тем больше станет утомлять постоянный ввод команд. Webpack может считывать опции из конфигурационного файла webpack.config.js в корневой директории проекта:
Теперь при каждом изменении index.js можно запускать webpack такой командой:
Больше не нужно определять опции index.js и bundle.js , потому что webpack загружает их из webpack.config.js. Так лучше, но всё равно утомительно вводить эту команду при каждом изменении кода. Надо ещё больше всё упростить.
Такой подход очень сильно повлиял на рабочий процесс. Мы уже не загружаем внешние скрипты с помощью глобальных переменных. Все новые JS-библиотеки будут добавлены в JavaScript с помощью выражений require , а не через теги в HTML. Наличие единственного JS-пакета зачастую повышает производительность. А после добавления этапа сборки появилось несколько мощных возможностей, которые тоже можно использовать в процессе разработки.
AMD модуль или RequireJS модуль
AMD (асинхронное определение модуля) — это шаблон для определения и использования модулей. Он используется в библиотеке RequireJS. AMD содержит функцию define для определения модуля, которая принимает название модуля, названия зависимостей и фабричную функцию:
Он также содержит функцию require для использования модуля:
require AMD отличается от require CommonJS тем, что в качестве аргументов функции принимает названия модулей и сами модули.
Динамическая загрузка
Функция define также имеет другое назначение. Она принимает функцию обратного вызова и передает похожую на CommonJS require этой функции. Внутри функции обратного вызова require вызывается для динамической загрузки модуля:
AMD модуль из CommonJS модуля
Приведенная выше функция define , кроме require , может принимать в качестве аргументов переменные exports и module . Поэтому внутри define может выполняться код из CommonJS:
Открытый модуль: шаблон открытого JS модуля
Шаблон открытого модуля был придуман Christian Heilmann. Этот шаблон также является IIFE, но акцент в нем делается на определении всех интерфейсов как локальных переменных внутри анонимной функции:
Такой синтаксис облегчает понимание того, за что отвечает (или что делает) каждый интерфейс.
3 ответа
источник, который вы цитируете, посвящен create-react-app , но автор ставит свои собственные взгляды сверху и представляет их так, как будто они являются установленным фактом.
Так что, во что бы то ни стало, используйте index.js , если вы хотите неявный импорт, но create-react-app этого не делает Это не важно, «не рекомендуется иметь index.js внутри этого каталога», и эта статья просто вводит в заблуждение. Есть причины для добавления index.js , и они совершенно не связаны с create-react-app , React в целом или даже практикой написания JS в форме класса.
Файл index.js хорошо использовать, когда у вас есть много компонентов, которые необходимо экспортировать из заданной папки, и вы хотите деструктурировать файлы, в которые вы их импортируете. Вам вовсе не обязательно следовать этому, но все же лучше всего поступать так; это может быть проще при экспорте большого количества файлов, например, из редуктора в Redux или из папки с большим количеством меньших компонентов, таких как или , и его легче читать другие пользователи, если все объединяется в один индексный файл, а не в несколько разных файлов.
У index.js есть специальные свойства, которые, если вы импортируете из файла, javascript будет искать index.js, если ничего не указано. Любой способ работает, но для более масштабных приложений предпочтительнее использовать index.js.
Это определенно стратегия, которую вы можете использовать для структурирования ваших компонентов. Если вы хотите, это зависит от вас. index.js по-разному обрабатывается веб-пакетом, поэтому вы можете просто import MyPage from './components/MyPage и оставить import.js в стороне. Обычный способ использовать эту практику - просто импортировать, а затем снова экспортировать компонент из index.js:
IIFE модуль: шаблон JS модуля
Определяя переменную в JS, мы определяем ее как глобальную переменную. Это означает, что такая переменная будет доступна во всех файлах JS, загружаемых на текущей странице:
Для того, чтобы избежать загрязнения глобального пространства имен, можно использовать анонимную функцию:
Вуаля, глобальных переменных больше нет. Однако код внутри функции не выполняется.
IIFE: немедленно вызываемое функциональное выражение
Для того, чтобы выполнить код внутри функции f , ее необходимо вызвать с помощью () как f() . Для выполнения кода внутри анонимной функции (() => <>) следует также использовать () . Это выглядит так (() => <>)() :
Это называется IIFE (немедленно вызываемым функциональным выражением). Модуль может быть определен следующим образом:
Мы оборачиваем код модуля в IIFE. Анонимная функция возвращает объект. Это заменяет интерфейс экспорта. Присутствует только одна глобальная переменная — название модуля (или его пространство имен). Впоследствии название модуля может использоваться для его вызова (экспорта). Это называется шаблоном JS модуля.
Примеси импорта
При определении модуля могут потребоваться некоторые зависимости. При использовании модульного шаблона каждый зависимый модуль — глобальная переменная. Зависимые модули могут определяться внутри анонимной функции или передаваться ей в качестве аргументов:
Ранние версии популярных библиотек, таких как jQuery, использовали этот шаблон (в последней версии jQuery используется UMD модуль).
Занятие 8. Файлы компонентов, структура React-проектов
▍Файлы компонентов
Если предположить, что вы выполняли задание из предыдущего практического занятия, используя стандартный проект, созданный create-react-app , то сейчас в нём задействован файл index.html из папки public , содержимое которого нас устраивает, и файл index.js из папки src , в котором мы пишем код. В частности, index.js выглядит сейчас примерно так:
Обратите внимание на то, что код функционального компонента MyInfo содержится именно в этом файле. Как вы помните, React позволяет создавать множество компонентов, в этом кроется одна из его сильных сторон. Понятно, что разместить код большого количества компонентов в одном файле, хотя и технически реализуемо, на практике означает большие неудобства. Поэтому код компонентов, даже небольших по объёму, обычно оформляют в виде отдельных файлов. Именно такому подходу и рекомендуется следовать при разработке React-приложений.
Файлам компонентов дают имена, соответствующие именам компонентов, код которых эти файлы хранят. Размещают их, в случае с create-react-app , в той же папке src , где расположен файл index.js . При таком подходе файл с компонентом MyInfo получит имя MyInfo.js .
Создадим файл MyInfo.js и перенесём в него код компонента MyInfo , удалив его из index.js .
На данном этапе работы index.js будет выглядеть так:
Код MyInfo.js будет таким:
Вот как всё это выглядит в VSCode.
Перенос кода компонента в новый файл
Код компонента из index.js мы перенесли, но получившаяся у нас сейчас структура пока ещё неработоспособна.
Во-первых, вспомните — для чего в index.js нужна команда import React from "react" , даже с учётом того, что мы напрямую к React здесь не обращаемся. Причина этого в том, что без импорта React не будут работать механизмы этой библиотеки, в частности — JSX. Именно благодаря этой команде импорта мы могли, на предыдущих занятиях, передавать методу ReactDOM.render() JSX-код и выводить HTML-разметку, создаваемую на его основе, на страницу. Всё это значит, что в файле MyInfo.js нам тоже нужно импортировать React. Это — обычная практика для файлов компонентов.
Во-вторых, нам нужно сделать так, чтобы функцией MyInfo из файла MyInfo.js можно было бы воспользоваться в других файлах приложения. Её для этого нужно экспортировать. Тут используются возможности стандарта ES6. В результате обновлённый код MyInfo.js принимает следующий вид:
Теперь поработаем над файлом index.js . А именно, нам нужно, чтобы компонент MyInfo был бы доступен в этом файле. Сделать его доступным в index.js можно, импортировав его.
Что если попробовать записать команду импорта компонента по образцу команд импорта react и react-dom в index.js ? Например, внесём в файл такую команду импорта:
Система, увидев такую команду, в частности, опираясь на то, что в ней отсутствуют сведения об относительном пути к файлу, будет искать зависимость проекта — модуль с именем, заданным при вызове этой команды (вот как устанавливать зависимости в проекты, созданные средствами create-react-app ; эти зависимости потом можно импортировать в React-проекты так же, как была импортирована библиотека React). Такого модуля она не найдёт, в результате команда импорта не сработает. Поэтому команду импорта файла нужно переписать с указанием пути к нему. В данном случае нас устроит указание на текущую директорию ( ./ ) и команда импорта приобретёт следующий вид:
Кроме того, если говорить о команде import , важно учитывать, что она подразумевает то, что с её помощью импортируются JavaScript-файлы. То есть расширение .js вполне можно убрать, и команда import , приобретя вид, показанный ниже, не утратит работоспособности.
Обычно подобные команды импорта JS-файлов записывают именно так.
Вот полный код файла index.js .
Использование средства запуска задач (task runner) (npm-скрипты)
Раз мы используем сборку при работе с модулями, имеет смысл подумать о средстве запуска задач — инструменте автоматизации разных операций процесса сборки. Во фронтенд-разработке это минификация, оптимизация изображений, прогон тестов и т. д.
В 2013-м самым популярным инструментом был Grunt, но вскоре его место занял Gulp. Оба используют плагины, играющие роль обёртки для других инструментов, которым нужна командная строка. Сегодня чаще всего применяется скриптинг, встроенный в npm, который напрямую работает с упомянутыми инструментами.
Давайте напишем npm-скрипт для упрощения работы с webpack. Для этого просто изменим package.json:
Здесь мы добавили два новых скрипта — build и watch . Для запуска сборочного скрипта введите команду:
Команда запускает webpack (с использованием конфигурации из сделанного ранее webpack.config.js) с опцией --progress , которая включает отображение прогресса в процентах, и с опцией -p для минимизации кода. Запустим скрипт watch :
Здесь используется опция --watch для автоматического перезапуска webpack при каждом изменении JavaScript-файла, это очень удобно для разработки.
Обратите внимание, что package.json может запускать webpack без указания полного пути ./node_modules/.bin/webpack, потому что node.js знает расположение каждого npm-модуля. Удобно! Сделаем ещё удобнее, установив webpack-dev-server, отдельный простой веб-сервер с функцией горячей перезагрузки. Установим в качестве зависимости среды разработки:
Теперь добавим npm-скрипт в package.json:
Можно запускать сервер разработки:
Команда автоматически открывает index.html в браузере по адресу localhost:8080 (по умолчанию). При изменении JavaScript-кода в index.js webpack-dev-server будет пересобирать свой собранный в пакет JavaScript и автоматически обновлять браузер. Это действительно экономит время, потому что можно сосредоточиться на коде, а не постоянно переключать внимание с кода на браузер, чтобы просматривать изменения.
Есть много других опций для webpack и webpack-dev-server, мы лишь прошлись по самым верхушкам (подробнее тут). Также вы можете написать npm-скрипты для других задач вроде конвертирования Sass в CSS, сжатия изображений, запуска тестов — всего, что использует командную строку. Также много классных советов можно почерпнуть из выступления Кейт Хадсон:
ES модуль: ECMAScript2015 или ES6 модуль
В 2015 году в 6 версии спецификации JS был представлен новый модульный синтаксис. Данная сецификаци получила название ECMAScript 2015 (ES2015) или ECMAScript 6 (ES6). Основа нового синтаксиса — ключевые слова import и export . Следующий код демонстирует использование ES модуля для именованного и «дефолтного» (по умолчанию) импорта/экспорта:
Для использования модульного файла в браузере необходимо добавить тег и определить его как модуль: . Для использования этого модуля в Node.js меняем его расширение на .mjs :
Для обратной совместимости в браузере можно добавить тег с атрибутом nomodule :
▍Структура проекта
При росте размеров и сложности React-проектов очень важно поддерживать в хорошем состоянии их структуру. В нашем случае, хотя наш проект сейчас и невелик, можно, в папке src , создать папку components , предназначенную для хранения файлов с кодом компонентов.
Создадим такую папку и переместим в неё файл MyInfo.js . После этого нужно будет отредактировать команду импорта этого файла в index.js .
А именно, сейчас путь к MyInfo.js указывает на то, что этот файл находится там же, где и index.js , но на самом деле файл этот теперь находится в папке components , находящейся в той же папке, что и index.js . В результате относительный путь к нему в index.js будет выглядеть так: ./components/MyInfo . Вот каким будет обновлённый код index.js :
А вот как всё это выглядит в VSCode.
Папка для хранения компонентов и импорт компонента из этой папки в VSCode
На самом деле, одна папка components , предназначенная для размещения кода всех компонентов — это пример чрезвычайно упрощённой структуры проекта. В реальных проектах, для обеспечения удобства работы с большим количеством сущностей, используются гораздо более сложные структуры папок. То, какими именно будут эти структуры, зависит от нужд проекта и от личных предпочтений программиста.
Рекомендуется поэкспериментировать со всем тем, о чём вы сегодня узнали. Например, можете попробовать переместить файл MyInfo.js в какую-нибудь папку и посмотреть — что из этого выйдет, можно попытаться переименовать его, поменять в нём какой-то код. Когда в ходе подобных экспериментов правильная работа проекта будет нарушена — полезно будет разобраться в проблеме и снова привести проект в работоспособное состояние.
UMD модуль: универсальное определение модуля или UmdJS модуль
UMD (универсальное определение модуля) — набор шаблонов для обеспечения работы модуля в разных средах выполнения.
UMD для AMD (RequireJS) и браузера
Следующий код обеспечивает работу модуля как в AMD (RequireJS), так и в браузере:
Выглядит сложно, но это всего лишь IIFE. Анонимная функция определяет наличие функции define из AMD/RequireJS.
- Если define обнаружена, фабричная функция вызывается через нее.
- Если define не обнаружена, фабричная функция вызывается напрямую. В этот момент аргумент root — это объект Window браузера. Он получает зависимые модули из глобальных переменных (свойств объекта Window). Когда factory возвращает модуль, он также становится глобальной переменной (свойством объекта Window).
UMD для AMD (RequireJS) и CommonJS (Node.js)
Следующий код обеспечивает работу модуля как в AMD (RequireJS), так и в CommonJS (Node.js):
Не пугайтесь, это снова всего лишь IIFE. При вызове анонимной функции, происходит «оценка» ее аргумента. Оценивание аргумента позволяет определить среду выполнения (определяется наличие переменных module и exports из CommonJS/Node.js, а также функции define из AMD/RequireJS).
- Если средой выполнения является CommonJS/Node.js, аргумент анонимной функции вручную создает функцию define .
- Если средой выполнения является AMD/RequireJS, аргументом анонимной функции является функция define из этой среды. Выполнение анонимной функции гарантирует работу функции define . Внутри анонимной функции для создания модуля вызывается функция define .
Итоги
На этом занятии мы поговорили об оформлении кода компонентов в виде отдельных файлов, об экспорте и импорте кода средствами ES6 и о структуре React-проектов. В следующий раз мы продолжим знакомиться с возможностями компонентов.
Browserify позволяет делать require («модули») в браузере, объединяя все ваши зависимости
Я не понял ни слова из предложения и стал разбираться, как это может помочь мне как разработчику.
Цель статьи — рассказать о контексте, в котором инструменты в JavaScript развивались вплоть до 2017-го. Начнём с самого начала и будем делать сайт, как это делали бы динозавры — безо всяких инструментов, на чистом HTML и JavaScript. Постепенно станем вводить разные инструменты, поочерёдно рассматривая решаемые ими проблемы. Благодаря историческому контексту вы сможете адаптироваться к постоянно меняющемуся ландшафту JavaScript и понять его.
Транспилирование кода ради новых возможностей языка (babel)
Транспилирование — это конвертация кода в другой, похожий язык. Это важная часть фронтенд-разработки: поскольку в браузерах медленно появляются новые фичи, были созданы языки с экспериментальными возможностями, которые транспилируются в совместимые с браузерами языки.
К примеру, для CSS есть Sass, Less и Stylus. Для JavaScript самым популярным транспилятором какое-то время был CoffeeScript (выпущен около 2010), а сегодня многие используют babel или TypeScript. CoffeeScript улучшает JavaScript за счёт серьёзного изменения языка — опциональное использование скобок, значимые отступы (whitespace) и т. д. Babel — это не новый язык, а транспилятор, который транспилирует JavaScript следующего поколения, имеющего возможности, пока недоступные во всех браузерах (ES2015 и выше), в старый и более совместимый JavaScript (ES5). Typescript — это язык, по существу аналогичный JavaScript следующего поколения, но с добавлением опциональной статичной типизации. Многие предпочитают babel, потому что он ближе к ванильному JavaScript.
Рассмотрим пример использования babel на этапе webpack-сборки. Сначала установим транспилятор (это npm-пакет) в проект:
Обратите внимание, что мы установили три отдельных пакета в качестве зависимостей среды разработки:
- babel-core — основная часть babel;
- babel-preset-env — пресет, определяющий, какие новые возможности JavaScript нужно транспилировать;
- babel-loader — пакет, позволяющий babel работать с webpack.
Сконфигурируем webpack для использования babel-loader , отредактировав файл webpack.config.js:
Синтаксис может вас запутать (к счастью, этот код не нужно часто редактировать). По сути, мы просим webpack найти все .js-файлы (за исключением лежащих в папке node_modules) и применить babel-транспилирование с помощью babel-loader и пресета babel-preset-env . Подробнее о синтаксисе конфигурирования webpack можно почитать здесь.
Всё настроено, можно использовать в нашем JavaScript возможности ES2015! Пример шаблонной строки (template string) ES2015 в файле index.js:
Для загрузки модулей можем воспользоваться выражением импортирования ES2015 вместо require , сегодня это встречается во многих кодовых базах:
В этом примере синтаксис import мало отличается от синтаксиса require , но import гибче в более сложных ситуациях. Раз мы изменили index.js, нужно снова запустить webpack:
Теперь обновим index.html в браузере. Когда я писал эту статью, большинство браузеров поддерживали все возможности ES2015, так что трудно сказать, заслуга ли это babel. Можете протестировать в старых браузерах вроде IE9 или поискать в bundle.js строку транспилированного кода:
Здесь babel транспилировал шаблонную строку ES2015 в обычное JavaScript-объединение строк, чтобы сохранить совместимость. Наверное, не самый впечатляющий пример, но транспилирование кода — очень мощный инструмент. В JavaScript можно добавить такие впечатляющие возможности, как async/await. И хотя транспилирование иногда бывает нудным и неприятным занятием, в последние годы оно помогло сильно улучшить язык, потому что многие разработчики сегодня тестируют возможности будущего.
Мы почти закончили, но в нашем рабочем процессе ещё остались шероховатости. Ради повышения производительности нужно минифицировать получившийся после сборки бандлером файл, но это довольно простая задача. Также нужно перезапускать webpack при каждом изменении JavaScript, который быстро устаревает. Рассмотрим инструменты для решения этих проблем.
ES динамический модуль: ECMAScript2020 или ES11 динамический модуль
В последней 11 версии спецификации JS 2020 года представлена встроенная функция import для динамического использования ES модулей. Данная функция возвращает промис, поэтому использовать модуль можно с помощью then :
Благодаря тому, что функция import возвращает промис, в ней может использоваться ключевое слово await :
Читайте также: