Привет, просто небольшое примечание: это было написано в 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]