Phoenix.LiveView.ColocatedJS
Исходный кодСпециальный HEEx :type, который во время компиляции извлекает любой код JavaScript из совместно расположенного тега <script>.
Примечание: для использования ColocatedJS необходим Phoenix 1.8 или новее.
Совместно расположенный JavaScript — это более обобщённая версия Phoenix.LiveView.ColocatedHook. Фактически совместно расположенные хуки построены поверх ColocatedJS.
С помощью ColocatedJS можно определять любой код JavaScript (веб-компоненты, глобальные обработчики событий и т. д.), которому не обязательно требуются возможности хуков. Например:
<script :type={Phoenix.LiveView.ColocatedJS} name="MyWebComponent">
export default class MyWebComponent extends HTMLElement {
connectedCallback() {
this.innerHTML = "Hello, world!";
}
}
</script>
Затем в файле app.js его можно импортировать следующим образом:
import colocated from "phoenix-colocated/my_app";
customElements.define("my-web-component", colocated.MyWebComponent);
В этом примере фактически не нужно добавлять специальный код веб-компонента в файл app.js, поскольку можно также напрямую вызвать customElements.define в совместно расположенном JavaScript. Однако этот пример показывает, как получить доступ к экспортированным значениям в своём бандле.
Примечание о зависимостях и umbrella-проектах
Для каждого приложения, использующего совместно расположенный JavaScript, в папке phoenix-colocated создаётся отдельный каталог. Это обеспечивает чёткое разделение хуков и кода зависимостей, а также приложений внутри umbrella-проектов.
Обычно зависимости по-прежнему объединяют собственные хуки и совместно расположенный JavaScript в отдельный файл перед публикацией. Однако простые хуки или фрагменты кода, которым не нужен доступ к сторонним библиотекам, можно также напрямую импортировать в свой бандл. Если библиотеке это необходимо, об этом должно быть указано в её документации.
Внутреннее устройство
При компиляции шаблона совместно расположенный JavaScript извлекается в специальную папку внутри Mix.Project.build_path(), которая называется phoenix-colocated. Её можно настроить, как описано ниже, но важно, чтобы это был каталог, не отслеживаемый системой контроля версий, поскольку исходным кодом служат компоненты. Кроме того, каталог используется несколькими приложениями (это также относится к приложениям в umbrella-проектах), поэтому обычно он должен быть общим, а не предназначенным для одного приложения.
Структура каталога совместно расположенного JS:
_build/$MIX_ENV/phoenix-colocated/ _build/$MIX_ENV/phoenix-colocated/my_app/ _build/$MIX_ENV/phoenix-colocated/my_app/index.js _build/$MIX_ENV/phoenix-colocated/my_app/MyAppWeb.DemoLive/line_HASH.js _build/$MIX_ENV/phoenix-colocated/my_dependency/MyDependency.Module/line_HASH.js ...
У каждого приложения есть собственная папка. Внутри неё для каждого модуля также создаётся отдельная папка, что позволяет отслеживать и удалять устаревший код.
Чтобы использовать совместно расположенный JS из app.js, необходимо настроить сборщик так, чтобы он разрешал поиск в папке phoenix-colocated. В новых приложениях Phoenix эта настройка уже добавлена в конфигурацию esbuild в файле config.exs:
config :esbuild,
...
my_app: [
args:
~w(js/app.js --bundle --target=es2022 --outdir=../priv/static/assets/js --external:/fonts/* --external:/images/* --alias:@=.),
cd: Path.expand("../assets", __DIR__),
env: %{"NODE_PATH" => [Path.expand("../deps", __DIR__), Mix.Project.build_path()]}
]
Здесь важна переменная среды NODE_PATH, которая указывает esbuild искать пакеты также в папке deps, а также Mix.Project.build_path(), которая указывает на _build/$MIX_ENV. Если используется другой сборщик, его нужно настроить соответствующим образом. Если настроить NODE_PATH невозможно, можно также изменить папку, в которую LiveView записывает совместно расположенный JavaScript, задав параметр :target_directory в файле config.exs:
config :phoenix_live_view, :colocated_assets,
target_directory: Path.expand("../assets/node_modules/phoenix-colocated", __DIR__)
В качестве альтернативы можно создать символическую ссылку на папку phoenix-colocated внутри папки node_modules.
Совет
Если удалить или изменить содержимое папки :target_directory, используйте mix clean --all и mix compile, чтобы заново сгенерировать весь совместно расположенный JavaScript.
Предупреждение!
LiveView предполагает, что полностью управляет настроенной папкой :target_directory. При компиляции он будет удалять все файлы и папки внутри :target_directory, которые не связаны с модулем совместно расположенного JavaScript или манифестом.
Импорт в совместно расположенном JS
Файлы совместно расположенного JS полностью обрабатываются сборщиком. В приложениях Phoenix это обычно esbuild. Поскольку совместно расположенный JS извлекается в папку за пределами стандартной папки assets, при импорте других файлов из совместно расположенного JS нужно соблюдать особую осторожность:
def sha256(assigns) do
~H"""
<div id="sha-256" phx-hook=".Sha256">Hello World</div>
<script :type={Phoenix.LiveView.ColocatedHook} name=".Sha256">
import { sha256 } from "my-example-sha256-library"
import { reverse } from "@/vendor/vendored-file"
export default {
mounted() {
this.el.innerHTML = sha256(reverse(this.el.innerHTML))
}
}
</script>
"""
end
Зависимости из node_modules должны работать без дополнительной настройки, но нельзя просто указать папку assets/vendor с помощью относительного пути. Вместо этого сборщик нужно настроить так, чтобы он обрабатывал псевдоним вида @ и разрешал его в локальную папку assets. В конфигурации esbuild для новых приложений Phoenix 1.8 эта настройка задана по умолчанию с помощью параметра alias в esbuild; это можно увидеть во фрагменте конфигурации выше (--alias=@=.).
Если расположение node_modules — не assets/node_modules и не node_modules, возможно, потребуется настроить параметр :node_modules_path:
# mix.exs
def project do
[
...
compilers: [:phoenix_live_view] ++ Mix.compilers(),
phoenix_live_view: [colocated_js: [node_modules_path: "assets/node_modules"]],
...
]
end
В этом примере показано поведение по умолчанию.
Примечание: в отличие от :target_directory, :node_modules_path — это параметр конкретного проекта, который нужно задать в файле mix.exs.
Параметры
Совместно расположенный JavaScript можно настроить с помощью атрибутов тега <script>. Поддерживаются следующие атрибуты:
name— имя, под которым экспорт по умолчанию скрипта доступен при импорте манифеста. Если атрибут не указан, файл будет импортирован только ради побочных эффектов.key— пользовательский ключ для экспорта. Он используетсяPhoenix.LiveView.ColocatedHook, чтобы экспортировать все хуки под именованным экспортомhooks(export { ... as hooks }). Например, для каждого совместно расположенного скрипта, определяющего веб-компонент, можно задать значениеweb_components, а затем импортировать их все какimport { web_components } from "phoenix-colocated/my_app". По умолчанию используется значение:default, то есть экспорт будет доступен под экспортомdefaultманифеста. Значение должно быть допустимым идентификатором JavaScript. Если этот атрибут задан, также требуетсяname.extension— пользовательское расширение для извлечённого файла. По умолчанию используетсяjs.manifest— пользовательский файл манифеста вместо стандартногоindex.js. Например,web_components.ts. Если изменить манифест, потребуется также изменить пути импорта JavaScript.
© 2014 Chris McCord
Licensed under the MIT License.
https://phoenix-live-view.hexdocs.pm/Phoenix.LiveView.ColocatedJS.html