Привет, просто небольшое примечание: это было написано в 2018 году. Надеюсь, здесь все еще есть некоторые полезные элементы, но многие из этих функций, возможно, изменились за годы, прошедшие с тех пор, как я написал это. Я не проверял! Удачного кодирования 👍
Начиная с выпуска Firefox в мае 2018 года, все основные браузеры теперь изначально поддерживают модули ES6! Никогда не используя модули широко, я начал несколько простых тестов, чтобы начать работу… и сразу же столкнулся с проблемами. Кажется, что много случайной литературы о модулях на самом деле посвящено тому, как такие продукты, как Webpack или Babel, используют модули, и есть тонкие и важные различия по сравнению с тем, как это было реализовано в собственном JavaScript.
Вот проблемы, с которыми я столкнулся, и способы их решения. Надеюсь, эта статья сэкономит кому-нибудь кучу времени :-)
Заблокировано CORS
Кажется, что Firefox и Edge нормально загружают модули в локальные файлы, но Chrome выдает эту ошибку:
Доступ к скрипту в «file: /// C: /path/to/main.js» из источника «null» заблокирован политикой CORS: недопустимый ответ. Следовательно, к источнику "null" доступ не разрешен.
Я получаю, что для многих крупных проектов уже есть жесткие требования к серверам, которые должны работать во время разработки (например, React), но для многих небольших проектов я сначала просто использую локальные файлы. Похоже, что Chrome обрабатывает модули с более высоким уровнем безопасности, чем Firefox или Edge, и бросает этот C ross O rigin R esource S ошибка, говорящая, что локальные файлы не из одного и того же источника.
Исправление для этого - запускать файлы вашего проекта с сервера. Я использую самый простой от NPM под названием http-сервер.
type = «модуль»
Самое замечательное в модулях то, что вы можете import
и export
использовать функции между файлами. В какой-то момент ваш основной HTML-файл должен будет иметь хотя бы один тег скрипта, который загружает ваш основной файл. В этом случае ваш тег скрипта должен иметь новый атрибут типа, равный модулю, например:
<script src="main.js" type="module"></script>
Если вы не укажете type="module"
, вы получите много разных ошибок, которые очень сбивают с толку:
Fire Fox
SyntaxError: объявления импорта могут появляться только на верхнем уровне модуля
Хром
Uncaught SyntaxError: неожиданный идентификатор
Край
SCRIPT1086: SCRIPT1086: здесь неожиданный оператор импорта или экспорта модуля
Firefox особенно плох, потому что он описывает другую ошибку, которая может быть правдой, но на самом деле это не проблема (это относится к тому факту, что, по сути, вы не можете поместить export
в предложение _5 _ / _ 6_ или в любой петле).
В любом случае добавьте type="module"
в свой тег скрипта.
Вы должны экспортировать значение по умолчанию
Это почти всегда не учитывается в руководствах по началу работы, которые состоят из небольших фрагментов примеров. Все модули должны определять значение по умолчанию export
, и если это не так, возникают следующие ошибки:
Fire Fox
SyntaxError: импорт не найден: по умолчанию
Хром
Uncaught SyntaxError: запрошенный модуль ‘./modulename.js’ не предоставляет экспорт с именем ‘default’
Edge - на самом деле не выдает ошибку, но также не может загрузить модуль: - \
Хорошая практика - подумать о том, каким будет export
по умолчанию, но в данном случае это действительно необходимо. Однако вы должны быть осторожны при экспорте, как мы увидим в следующем разделе ...
Экспорт «правильным путем»
Для удобства чтения я всегда использую инструкции import
и export
в самом верху файла, это хороший обзор и настройка контекста для того, что будет ниже. Синтаксис export
и import
допускает несколько вариаций, но только некоторые из них работают в определенных ситуациях… в основном связанные с областью видимости переменных.
Это, например, дает вам ошибки:
export default count; export {ability}; let count = 10; function ability() { return 'hello!'; }
Fire Fox
ReferenceError: невозможно получить доступ к лексическому объявлению count перед инициализацией.
Хром
modulename.js: 1 Uncaught ReferenceError: счетчик не определен
в modulename.js: 1
Край
SCRIPT5113: Использовать перед объявлением
Здесь нужно знать две вещи: Во-первых, если экспорт по умолчанию является функцией, вы можете сделать это:
export default ability; export {count}; let count = 10; function ability() { return 'hello!'; }
Нет проблем - проблема возникает только с let
или const
переменными. Кроме того, если вы действительно хотите экспортировать переменную по умолчанию в верхней части файла, вы можете сделать это:
export {count as default}; export {ability}; let count = 10; function ability() { return 'hello!'; }
Импортируйте «правильный путь»
Импорт должен заканчиваться на .js
.
Функциональность модульного типа была доступна ранним последователям уже некоторое время благодаря использованию транспайлеров. Но синтаксис таких вещей, как require('modulename')
и модули ES6, немного отличается. Один из первых моментов заключается в том, что модули ES6 должны быть полными именами файлов, иначе они будут вызывать ошибки:
import {count} from './modulename';
Fire Fox
Не удалось загрузить модуль с исходным кодом http://127.0.0.1:8080 большая/modulename.
Хром
GET http://127.0.0.1:8080 форма «/start 404 (Not Found)
Edge - на самом деле не выдает ошибку, но также не может загрузить модуль: - \
Простое добавление суффикса .js
исправляет это:
import {count} from './modulename.js';
Именованный импорт заключен в квадратные скобки, по умолчанию квадратные скобки нет.
Это может быть очень сложно… по большей части, когда я что-то экспортирую, я импортирую это в другой модуль с тем же именем. Однако это не обязательно. Вернемся к нашему супер базовому примеру:
export {count as default}; export {ability}; let count = 10; function ability() { return 'hello!'; }
Теперь в другом файле я импортирую вещи:
import ability from './modulename.js';
Здесь для импорта ability
нет скобок, что означает, что ему будет назначен экспорт по умолчанию. В этом случае экспортом по умолчанию фактически является переменная count
, равная числу 10, в отличие от функции.
Если мы хотим импортировать конкретную именованную вещь, используйте фигурные скобки:
import {ability} from './modulename.js';
Теперь он просматривает экспорт modulename.js
, ищет ability
по имени и создает локальное импортированное значение с тем же именем.
Есть много-много других вариантов того, как экспортировать и импортировать вещи, я рекомендую вам прочитать страницы экспорт и импорт MDN. Эта небольшая разница между скобками и экспортом по умолчанию сначала сбивала с толку, так что это основная вещь, о которой нужно помнить.
Вот и все!
Как я уже сказал, надеюсь, это кому-то сэкономит время. Напишите мне вопросы или комментарии: [email protected]