На самом деле поддержка нативных модулей браузера отсутствует уже год или два (впервые я узнал об этом во второй половине 2016 года).
можно выброситьwebpackИспользовать напрямуюimportсинтаксис как
Но поскольку это относительно новая вещь, сейчас я могу играть только с самим собой :p
Но это не повод не узнавать об этом, а переживать.
Во-первых, когда основные браузеры начали поддерживатьmoduleиз:
- Safari 10.1
- Chrome 61
- Firefox 54 (может потребоваться
about:configнастройка страницы включенаdom.moduleScripts.enabled) - Edge 16
Как использовать
Прежде всего, в использовании, единственная разница в том, что вам нужно использовать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Приходите развивать день скорее :)
использованная литература
Репозиторий GitHub для примера кода в статье:массив телепортации