Попытка нативного ES-MODULE в вашем браузере

Node.js внешний интерфейс JavaScript браузер

На самом деле поддержка нативных модулей браузера отсутствует уже год или два (впервые я узнал об этом во второй половине 2016 года).
можно выброситьwebpackИспользовать напрямуюimportсинтаксис как
Но поскольку это относительно новая вещь, сейчас я могу играть только с самим собой :p
Но это не повод не узнавать об этом, а переживать.

Во-первых, когда основные браузеры начали поддерживатьmoduleиз:

  • Safari 10.1
  • Chrome 61
  • Firefox 54 (может потребоватьсяabout:configнастройка страницы включенаdom.moduleScripts.enabled)
  • Edge 16

данные изДжейк Арчибальд.com/2017/starve-to-touch…

Как использовать

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

<script type="module">
  import message from './message.js'

  console.log(message) // hello world
</script>

Затем в соответствующемmoduleфайл часто находится вwebpackкак используется в.
Синтаксически разницы нет(первоначальноwebpackТо есть, чтобы познакомить вас с новым синтаксисом :))

message.js

export default 'hello world'

изящная деградация

Вот похожийnoscriptналичие этикеток.
допустимыйscriptдобавить на ярлыкnomoduleАтрибуты для реализации схемы отката.

<script type="module">
  import module from './module.js'
</script>
<script nomodule>
  alert('your browsers can not supports es modules! please upgrade it.')
</script>

nomoduleРешение выглядит следующим образом: служба поддержкиtype="module"Браузеры игнорируют включениеnomoduleатрибутscriptВыполнение скрипта.
не поддерживаетсяtype="module"браузеры будут игнорироватьtype="module"исполнение скрипта.
Это связано с тем, что браузеры по умолчанию анализируют толькоtype="text/javascript"скрипт, а если не заполненtypeсвойство по умолчанию равноtext/javascript.
То есть браузер не поддерживаетmoduleна случай, если,nomoduleСоответствующий файл скрипта будет выполнен.

Некоторые детали, на которые следует обратить внимание

Но ведь он нативно предоставляется браузером, а способ использования тот же, что иwebpackОпределенно будут какие-то отличия в версии.
(по крайней мере один анализируется во время выполнения и один компилируется локально)

Правильное определение пути к модулю

Поскольку он реализован на стороне браузера, он не будет такимnode, Существует глобальныйmoduleОдин сказал (глобальные объекты находятся вwindowвнутри).
так,from 'XXX'Определение этого пути будет немного отличаться от того, с чем вы были знакомы ранее.

// 被支持的几种路径写法

import module from 'http://XXX/module.js'
import module from '/XXX/module.js'
import module from './XXX/module.js'
import module from '../XXX/module.js'

// 不被支持的写法
import module from 'XXX'
import module from 'XXX/module.js'

существуетwebpackВ упакованном файле на глобальный пакет ссылаются черезimport module from 'XXX'быть реализованным.
На самом деле это сокращение,webpackпойдет по этому путиnode_modulesнайти соответствующийmoduleи внесите.
но изначально поддерживаетсяmoduleне существуетnode_modulesОдин сказал.
Итак, используя роднойmoduleКогда нужно вспомнить,fromКонечный путь должен быть допустимымURL, и суффикс файла не должен быть опущен (Да, доступны даже удаленные файлы, в отличие отwebpackНужно упаковать локальные файлы вместе).

файл модуля по умолчанию откладывает

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

<script type="module" src="./defer/module.js"></script>
<script src="./defer/simple.js"></script>
<script defer src="./defer/defer.js"></script>

Чтобы проверить изложенную выше точку зрения, на странице представлены следующие триJSфайл, все три файла выведут строку, вConsoleПорядок, видимый на панели, таков:

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

Потому что в обычном сценарииdeferКлючевое слово относится только к файлу сценария, если онinline-script, добавление атрибута не вступает в силу.
Но когдаtype="module", будь то файл или встроенный скрипт, он будет иметьdeferхарактеристики.

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

asyncЭто может действовать на всеmoduleтип сценария, либо встроенный, либо в виде файла.
но добавилasyncКлючевое слово Later не означает, что браузер будет выполняться при анализе файла сценария, а будет ждать, пока будут выполнены все сценарии, от которых зависит сценарий.moduleВыполнить после загрузки.
Соглашение об импорте должно быть объявлено в начале фрагмента кода и не может быть выполнено внутри функции.

То есть дноlogПорядок вывода полностью зависит отmodule.jsПродолжительность загрузки.

<script async type="module" >
  import * from './module.js'
  console.log('module')
</script>
<script async src="./defer/async.js"></script>

Модуль будет загружен только один раз

этоmoduleЕдинственное определение состоит в том, согласован ли полный путь, соответствующий ресурсу.
Если текущий путь к страницеhttps://www.baidu.com/a/b/c.html, то файл в/module.js,../../module.jsа такжеhttps://www.baidu.com/module.jsсчитаются одинаковымиmodule.
Но как в этом примереmodule1.jsа такжеmodule1.js?a=1определены как дваmodule, поэтому результатом выполнения этого кода является то, что он будет загружен дваждыmodule1.js.

<script type="module" src="https://blog.jiasm.org/module-usage/example/modules/module1.js"></script>
<script type="module" src="/examples/modules/module1.js"></script>
<script type="module" src="./modules/module1.js"></script>
<script type="module" src="./modules/module1.js?a=1"></script>
<script type="module">
  import * as module1 from './modules/module1.js'
</script>

Онлайн-демонстрация

Несколько советов по использованию импорта и экспорта

Является ли это версией, изначально предоставленной браузером, илиwebpackупакованная версия.
importа такжеexportПо сути, это все еще распространено, и в грамматике нет разницы в грамматике.

Ниже перечислены некоторые из них, которые могут помочь вам лучше использоватьmodulesнекоторые трюки.

переименование экспорта

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

// info.js
let name = 'Niko'
let age = 18

export {
  name as firstName,
  age
}

// import
import {firstName, age} from './info.js'

Советы: экспортные вызовы в отличие от Module.exports = {} в Node.exports = {}
Можно сделать несколько вызовов без перезаписи (за исключением повторяющихся имен ключей).

export { name as firstName }
export { age }

Таким образом, оба ключа будут экспортированы.

Все атрибуты, экспортируемые при экспорте, доступны для чтения.

то естьexportЭкспортированные свойства нельзя изменить, и вы получите исключение, если попытаетесь это сделать.
Однако что-то вродеconstЭффект, если экспортируемое значение является ссылочным типом, таким как объект или массив.
Вы можете манипулировать некоторыми свойствами объекта, например, делатьpushтакие операции.

export {
  firstName: 'Niko',
  packs: [1, 2]
}
import * as results from './export-editable.js'

results.firstName = 'Bellic' // error

results.packs.push(3)        // success

Такая модификация повлияет на другие ссылки на модуль, поскольку используется адрес.

Порядок экспорта в коде не влияет на конечный результат экспорта

export const name = 'Niko'
export let age = 18

age = 20

const или let не имеет значения для вызывающего

import {name, age} from './module'

console.log(name, age) // Niko 20

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

ПолучатьdefaultДостичь можно несколькими способами:

import defaultItem from './import/module.js'
import { default as defaultItem2 } from './import/module.js'
import _, { default as defaultItem3 } from './import/module.js'

console.log(defaultItem === defaultItem2) // true
console.log(defaultItem === defaultItem3) // true

Правило по умолчанию состоит в том, что первоеdefaultСоответствующий псевдоним, но если первый аргумент является деструктурированием, он будет разрешен для совпадения для всех экспортов.
P.S. Параметров одновременно два, указывающих, что первый дефолтный, а второй все модули

Синтаксис экспорта всего следующий:

import * as allThings from './iport/module.js'

Запись файла экспорта, аналогичного индексу

Если вы столкнетесь с такой потребностью, в некоторых местах будет использоваться десятьmodule, если каждый разimportДесять, это определенно пустая трата времени, и это также вызовет у людей неприятные ощущения визуально.
Итак, вы можете написать что-то вродеindex.jsфайл, в этом файле он вводится в блок, а затем при использованииimport indexВот и все.
В общем можно написать так:

import module1 from './module1.js'
import module2 from './module2.js'

export default {
  module1,
  module2
}

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

export {default as module1} from './module1.js'
export {default as module2} from './module2.js'

Затем измените его на следующий формат при вызове:

import * as modules from './index.js'

Онлайн-демонстрация

Примечания

Напоминает мне о недавнем бумеdeno, так же упоминается одна из фич, нетnode_modules, зависимые сторонние библиотеки получаются напрямую через сетевые запросы.
Затем изначально предоставляется в браузереmoduleЭто также аналогичная реализация, но все движется в более гибком направлении.
желание отказатьсяwebpackПриходите развивать день скорее :)

использованная литература

  1. es modules in browsers
  2. es6 modules in depth
  3. export - JavaScript | MDN
  4. import - JavaScript | MDN

Репозиторий GitHub для примера кода в статье:массив телепортации