Как кэшировать js библиотеку при импорте
Перейти к содержимому

Как кэшировать js библиотеку при импорте

  • автор:

Экспорт и импорт

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

В предыдущей главе мы видели простое использование, давайте теперь посмотрим больше примеров.

Экспорт до объявления

Мы можем пометить любое объявление как экспортируемое, разместив export перед ним, будь то переменная, функция или класс.

Например, все следующие экспорты допустимы:

// экспорт массива export let months = ['Jan', 'Feb', 'Mar', 'Apr', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec']; // экспорт константы export const MODULES_BECAME_STANDARD_YEAR = 2015; // экспорт класса export class User < constructor(name) < this.name = name; >>

Не ставится точка с запятой после экспорта класса/функции

Обратите внимание, что export перед классом или функцией не делает их функциональным выражением. Это всё также объявление функции, хотя и экспортируемое.

Большинство руководств по стилю кода в JavaScript не рекомендуют ставить точку с запятой после объявлений функций или классов.

Поэтому в конце export class и export function не нужна точка с запятой:

export function sayHi(user) < alert(`Hello, $!`); > // без ; в конце

Экспорт отдельно от объявления

Также можно написать export отдельно.

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

// �� say.js function sayHi(user) < alert(`Hello, $!`); > function sayBye(user) < alert(`Bye, $!`); > export ; // список экспортируемых переменных

…Или, технически, мы также можем расположить export выше функций.

Импорт *

Обычно мы располагаем список того, что хотим импортировать, в фигурных скобках import <. >, например вот так:

// �� main.js import from './say.js'; sayHi('John'); // Hello, John! sayBye('John'); // Bye, John!

Но если импортировать нужно много чего, мы можем импортировать всё сразу в виде объекта, используя import * as . Например:

// �� main.js import * as say from './say.js'; say.sayHi('John'); say.sayBye('John');

На первый взгляд «импортировать всё» выглядит очень удобно, не надо писать лишнего, зачем нам вообще может понадобиться явно перечислять список того, что нужно импортировать?

Для этого есть несколько причин.

    Современные инструменты сборки (webpack и другие) собирают модули вместе и оптимизируют их, ускоряя загрузку и удаляя неиспользуемый код. Предположим, мы добавили в наш проект стороннюю библиотеку say.js с множеством функций:

// �� say.js export function sayHi() < . >export function sayBye() < . >export function becomeSilent()

Теперь, если из этой библиотеки в проекте мы используем только одну функцию:

// �� main.js import from './say.js';

Импорт «как»

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

Например, для краткости импортируем sayHi в локальную переменную hi , а sayBye импортируем как bye :

// �� main.js import from './say.js'; hi('John'); // Hello, John! bye('John'); // Bye, John!

Экспортировать «как»

Аналогичный синтаксис существует и для export .

Давайте экспортируем функции, как hi и bye :

// �� say.js . export ;

Теперь hi и bye – официальные имена для внешнего кода, их нужно использовать при импорте:

// �� main.js import * as say from './say.js'; say.hi('John'); // Hello, John! say.bye('John'); // Bye, John!

Экспорт по умолчанию

На практике модули встречаются в основном одного из двух типов:

  1. Модуль, содержащий библиотеку или набор функций, как say.js выше.
  2. Модуль, который объявляет что-то одно, например модуль user.js экспортирует только class User .

По большей части, удобнее второй подход, когда каждая «вещь» находится в своём собственном модуле.

Естественно, требуется много файлов, если для всего делать отдельный модуль, но это не проблема. Так даже удобнее: навигация по проекту становится проще, особенно, если у файлов хорошие имена, и они структурированы по папкам.

Модули предоставляют специальный синтаксис export default («экспорт по умолчанию») для второго подхода.

Ставим export default перед тем, что нужно экспортировать:

// �� user.js export default class User < // просто добавьте "default" constructor(name) < this.name = name; >>

Заметим, в файле может быть не более одного export default .

…И потом импортируем без фигурных скобок:

// �� main.js import User from './user.js'; // не , просто User new User('John');

Импорты без фигурных скобок выглядят красивее. Обычная ошибка начинающих: забывать про фигурные скобки. Запомним: фигурные скобки необходимы в случае именованных экспортов, для export default они не нужны.

Именованный экспорт Экспорт по умолчанию
export class User

export default class User
import from . import User from .

Технически в одном модуле может быть как экспорт по умолчанию, так и именованные экспорты, но на практике обычно их не смешивают. То есть, в модуле находятся либо именованные экспорты, либо один экспорт по умолчанию.

Так как в файле может быть максимум один export default , то экспортируемая сущность не обязана иметь имя.

Например, всё это – полностью корректные экспорты по умолчанию:

export default class < // у класса нет имени constructor() < . >>
export default function(user) < // у функции нет имени alert(`Hello, $!`); >

Модули JavaScript, как правильно импортировать

Предположим в главном .js файле я импортирую 2 модуля. В каждом из этих модулей я использую одну и ту же библиотеку, поэтому в каждом из них я прописываю необходимые для нее import’ы. Означает ли это что при импорте этих модулей в главный .js файл код библиотеки скопируется 2 раза? Или js умный и поймет что это одинаковые импорты и не будет второй раз импортировать библиотеку в главный js? Использую WebPack для сборки.

Отслеживать
hot_penguin
задан 13 июл 2021 в 11:09
hot_penguin hot_penguin
470 1 1 золотой знак 4 4 серебряных знака 16 16 бронзовых знаков

Наверное, стоит уточнить в вопросе: речь идет о бандлерах, или о стандартном импорте без участия утилит-сборщиков. Сборщики нередко трансформируют код (зависит от их настроек), например из ESM делают UMD. при такой трансформации, вопрос обретает совсем другой смысл 🙂

13 июл 2021 в 11:56
использую WebPack
14 июл 2021 в 7:27

Я голосую за закрытие этого вопроса, потому что он не содержит технических подробностей требуемых для однозначного ответа (таких как: формат модулей, способ их импорта, используемые инструменты сборки и их конфигурация, условия воспроизведения ситуации, и т.д.). В текущей формулировке, вопрос предполагает обобщенные/размытые ответы, которые не принесут пользу сообществу.

Как работают нативные JavaScript imports

Владимир Шайтан

Как работают нативные JavaScript imports

Lead Front-end Developer в One Source, Преподаватель Компьютерной школы Hillel.

  1. 1. Навіщо потрібні import-и ?
  2. 2. Как работают import-ы
  3. 3. Как V8 JavaScript Engine делает импорты?
  4. 4. Как использовать import?
  5. 5. О динамическом импорте
  6. 6. Интересное
  7. 7. Вывод

Стандарт EcmaScript 2015 (ES6) ввел новый инструмент для работы с модулями JavaScript, известный как import. Этот инструмент позволяет легко импортировать функции, классы, переменные и объекты из других файлов, создавая модульную структуру вашего кода.

В этой статье мы рассмотрим, как работают нативные JavaScript import-ы. Важно понимать, что в этом материале мы не затрагиваем тему того, как работают импорты в инструментах сборки, например, webpack.

Зачем нужны import-ы?

Модульный код помогает разделить программу на логические части (модули), что облегчает организацию, поддержку и расширение кода.

Он способствует повторному использованию кода, изолирует переменные и функции других модулей, упрощает тестирование и развитие программы и облегчает сотрудничество разработчиков. Также модульный код использует ключевое слово import для импорта функций, классов и переменных из других модулей и поддерживает использование сторонних библиотек для улучшения функциональности.

Как работают import-ы

Импорты в JavaScript определяются спецификацией EcmaScript (ES6 и более поздних версий). Под капотом механизм импорта включает в себя несколько ключевых аспектов:

Размещение файлов

Когда вы производите импорт в JavaScript, вы указываете путь к файлу, который нужно импортировать. Этот путь может быть абсолютным или относительным, и браузер (или среда выполнения, если это Node.js) выполняет запрос на сервер для загрузки этого файла.

HTTP-запрос

Браузер (или среда выполнения) делает HTTP-запрос на сервер для загрузки файла, указанного в импорте. Это может быть GET-запросом или другими HTTP-методами.

Загрузка файла

Сервер обрабатывает запрос и посылает содержимое файла на клиентскую сторону. Файл загружается в память.

Выполнение кода

После загрузки файла содержимое файла обрабатывается и выполняется в среде выполнения (браузер или Node.js). Если файл содержит импорты, импортируемые модули также загружаются и выполняются.

Область видимости

Импортируемые переменные или функции становятся доступными в области видимости импортируемого файла.

// module.js export function greet(name) < console.log(`Hello, $!`); > // main.js import < greet >from './module.js'; greet('Alice');

Во время выполнения main.js браузер (или Node.js) выполнит HTTP-запрос в файл module.js, загрузит его содержимое, выполнит функцию greet и выведет «Hello, Alice!».

Как V8 JavaScript Engine делает импорты?

V8 — это виртуальная машина JavaScript, которая используется в браузерах и Node.js для выполнения JavaScript-кода. V8 взаимодействует с импортами в JavaScript через стандартные механизмы ECMAScript (ES6 и более поздних версий).

Рассмотрим, как V8 обрабатывает импорты:

Анализ и парсинг:

При анализе и парсинге импортируемых файлов JavaScript-движок (в нашем случае, V8) разбирает входящий текст кода и идентифицирует ключевые слова import и export. Он также распознает импортируемые и экспортируемые имена. Парсер понимает синтаксис языка и определяет структуру модуля.

Распознавание путей:

Во время парсинга V8 распознает пути к импортируемым файлам. Он определяет, являются ли эти пути абсолютными (начинаются с `/`) или относительными (начинаются с `./` или `../`). Внутренняя логика определяет, какой файл нужно скачать.

Загрузка файлов:

V8 инициирует загрузку файлов, указанных в импортах.

В веб-браузерах это может включать выполнение HTTP-запроса на сервер с помощью API, такого как `fetch`, для получения содержимого файла. В среде Node.js это может включать в себя обращение к файловой системе для чтения файла с диска.

Кэширование импортов:

Для оптимизации производительности V8 может кэшировать импортируемые файлы во избежание повторной загрузки. Если этот файл импортируется несколько раз в разных частях кода, он может быть взят из кэша, что уменьшает нагрузку на сеть или файловую систему.

Выполнение кода:

После загрузки V8 обрабатывает содержимое импортированных файлов и выполняет код JavaScript.

Это включает выполнение всех импортируемых модулей и установку связей между экспортируемыми и импортируемыми объектами. Выполнение кода включает обработку функций, переменных, классов и любого другого кода, содержащегося в импортированных файлах.

Построение зависимостей:

V8 следит за зависимостями между модулями и обеспечивает, что модули всегда загружаются в правильном порядке. Это помогает избежать циклических зависимостей и обеспечить корректное исполнение кода.

Этот механизм позволяет разработчикам создавать структуру проекта, состоящую из разных модулей, и использовать их в соответствии с потребностями.

События и обработка ошибок:

V8 отслеживает события загрузки и выполнения модулей и обрабатывает ошибки, если они возникают в ходе этих операций.

Это может включать в себя обработку ошибок отсутствия файла, ошибок синтаксиса или других видов ошибок. Обработка ошибок помогает идентифицировать и устранить проблемы с импортами.

Область видимости:

После загрузки и выполнения модуля импортируемые объекты (функции, переменные, классы) становятся доступными в области видимости модуля, который делает импорт.

Вы можете использовать их в коде, импортирующем модуль. Механизм области видимости помогает изолировать переменные и функции одного модуля от других, уменьшая возможные конфликты и облегчая управление кодом.

Эти механизмы взаимодействуют, чтобы позволить создавать структурированный и модульный код JavaScript.

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

Импорты в JavaScript (JS) и TypeScript (TS) — это способ включить функциональность из других модулей (файлов) в ваш код. Это помогает организовать проект и поддерживать чистоту кода, разделяя его на меньшие, самостоятельные части.

У JavaScript и TypeScript существует несколько способов импорта. Рассмотрим основные с простейшими примерами на языке JavaScript.

Default Imports (импорт по умолчанию):

В файле module.js мы можем иметь функцию по умолчанию, которую мы хотим импортировать.

// module.js export default function greet(name) < console.log(`Hello, $!`); >

В другом файле мы можем импортировать эту функцию так:

// main.js import greet from './module.js'; greet('Alice');

Named Imports (импорт по имени):

// module.js export function greet(name) < console.log(`Hello, $!`); > export function farewell(name) < console.log(`Goodbye, $!`); >

В другом файле мы импортируем их так:

// main.js import < greet, farewell >from './module.js'; greet('Charlie'); farewell('David');

Aliasing (импорт с псевдонимами):

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

// module.js export function greet(name) < console.log(`Hello, $!`); > // main.js import < greet as sayHello >from './module.js'; sayHello('Grace');

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

О динамическом импорте

Динамический импорт — это механизм JavaScript, позволяющий загружать модули не в момент компиляции, а во время выполнения программы. Он придает большую гибкость и позволяет оптимизировать загрузку модулей, особенно в больших приложениях.

Синтаксис

Для того чтобы использовать динамический импорт, вы используете ключевое слово import() вместо обычного import.

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

const dynamicImport = import('./myModule.js');

Использование Promise:

Объект, возвращаемый из import(), является обещанием (Promise). Вы можете использовать метод .then() или ключевое слово await для решения этого обещания и выполнения кода, когда модуль загружен.

Пример использования .then():

dynamicImport .then((module) => < // Використання завантаженого модуля >) .catch((error) => < // Обробка помилки завантаження >);

Пример использования await:

try < const module = await dynamicImport; // Використання завантаженого модуля >catch (error) < // Обробка помилки завантаження >

Ленивая загрузка

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

В зависимости от переменных

Динамический импорт позволяет загружать модули на основе значений переменных или результатов функций. Например, можно сконструировать путь к модулю на основе пользовательского ввода или на других условиях.

const moduleName = 'myModule'; const dynamicImport = import(`./$.js`);

Интересное

Импорт в форме export* from …

Вы можете импортировать все экспорты из другого модуля с помощью export*.

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

export * from './myModule.js';

Внешний импорт файлов

В некоторых случаях, кроме загрузки модулей JavaScript, можно импортировать другие типы файлов, такие как изображения или стили CSS.

Это позволяет включать содержание файлов непосредственно в свой код.

import myImage from './myImage.png';

Модульные импорты в HTML

Вы можете использовать импорты модулей непосредственно в HTML-файлах, чтобы загружать и выполнять JavaScript-код при загрузке страницы.

  

Динамические ключи для импорта

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

const moduleName = 'myModule'; import(`./$.js`) .then((module) => < // Використання завантаженого модуля >);

Вывод

Использование импортов в JavaScript имеет множество преимуществ:

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

  • Разделение функциональности:

Вы можете импортировать только те части кода, которые вам нужны, вместо загрузки всего. Это уменьшает объем загруженного кода и улучшает производительность.

  • Сохранность ресурсов:

Импорты позволяют загружать ресурсы, такие как изображения или стили, только если они нужны, что облегчает оптимизацию загрузки страницы.

  • Зависимость и поддержка:

Импорты помогают управлять зависимостями вашего проекта и облегчают обновление модулей.

  • Ленивая загрузка:

Некоторые импорты могут быть загружены «линейно», то есть только тогда, когда они фактически нужны, уменьшая время загрузки страницы.

  • Удобство и читабельность:

Импорты делают код более понятным, так как они указывают, откуда загружены символы или функции.

Все эти преимущества делают импорты важным инструментом для разработки как небольших, так и крупных приложений JavaScript.

Рекомендуем курс по теме

Владимир Шайтан

Lead Front-end Developer в One Source, Преподаватель Компьютерной школы Hillel.

Как кэшировать js библиотеку при импорте

Использование существующих библиотек JavaScript в клиентских веб-частях SharePoint Framework

Для создания клиентских веб-частей на платформе SharePoint Framework можно использовать существующие библиотеки JavaScript. Однако существует ряд факторов, которые следует учитывать, чтобы веб-части не снижали скорость загрузки страниц SharePoint, на которых они используются.

Ссылка на существующие библиотеки как на пакеты

Наиболее распространенный способ ссылки на существующие библиотеки JavaScript в клиентских веб-частях SharePoint Framework предполагает их установку в проекте в виде пакета.

    Например, чтобы использовать Angular в клиентской веб-части, сначала нужно установить его с помощью npm:

npm install angular --save 
npm install @types/angular --save-dev 
import < Version >from '@microsoft/sp-core-library'; import < BaseClientSideWebPart, IPropertyPaneConfiguration, PropertyPaneTextField >from '@microsoft/sp-webpart-base'; import < escape >from '@microsoft/sp-lodash-subset'; import styles from './HelloWorld.module.scss'; import * as strings from 'helloWorldStrings'; import < IHelloWorldWebPartProps >from './IHelloWorldWebPartProps'; import * as angular from 'angular'; export default class HelloWorldWebPart extends BaseClientSideWebPart `; angular.module('helloworld', []); angular.bootstrap(this.domElement, ['helloworld']); > // omitted for brevity > 

Объединение ресурсов веб-части в пакет

Платформа SharePoint Framework использует цепочку инструментов для сборки, основанную на инструментах с открытым кодом, таких как gulp и Webpack. При создании проектов SharePoint Framework эти инструменты для сборки автоматически объединяют все ресурсы, на которые ссылается веб-часть, в один файл JavaScript. Этот процесс называется объединением.

Командное окно с задачей gulp bundle рядом с папкой dist SharePoint Framework с выходными файлами

У объединения в пакет есть ряд преимуществ. Во-первых, все ресурсы, необходимые веб-части, доступны в одном файле JavaScript. Это упрощает развертывание, так как веб-часть состоит из одного файла, и в процессе развертывания невозможно пропустить зависимость.

Так как веб-часть использует разные ресурсы, важно, чтобы они загружались в правильном порядке. Пакет веб-части, созданный средством Webpack при сборке, автоматически управляет загрузкой разных ресурсов, в том числе сопоставляет зависимости между ними.

У объединения веб-частей также есть преимущества для пользователей: быстрее скачать один большой файл, чем несколько маленьких. Веб-часть быстрее загружается на странице.

Но объединение существующих библиотек JavaScript с клиентскими веб-частями SharePoint Framework не лишено недостатков.

При объединении существующих платформ JavaScript на базе SharePoint Framework в пакет включаются все сценарии, на которые ссылается веб-часть. Например, размер оптимизированного пакета веб-части с Angular — более 170 КБ.

Снимок экрана: папка развертывания на экране проводника с выделенным файлом JavaScript пакета Hello World.

Если вы добавите в проект еще одну веб-часть на Angular и выполните сборку проекта, то получите два пакета размером более 170 КБ — по одному для каждой веб-части.

Снимок экрана: папка развертывания на экране проводника с двумя выделенными файлами JavaScript пакета Hello World.

Если вы добавите эти веб-части на страницу, каждый пользователь скачает Angular несколько раз. Этот подход неэффективен и замедляет загрузку страницы.

Ссылка на существующие библиотеки как на внешние ресурсы

Предпочтительный способ использования существующих библиотек в клиентских веб-частях SharePoint Framework — сослаться на них как на внешние ресурсы. В этом случае в веб-часть будет включаться только URL-адрес сценария. При добавлении на страницу веб-часть автоматически попытается загрузить все необходимые ресурсы с указанного URL-адреса.

Ссылаться на существующие библиотеки JavaScript на платформе SharePoint Framework легко, и для этого не требуется изменять код. Так как библиотека загружается при запуске с указанного URL-адреса, ее не нужно устанавливать как пакет в проекте.

Например, чтобы сослаться на Angular как на внешний ресурс в клиентской веб-части, сначала установите объявления типов TypeScript с помощью npm:

npm install @types/angular --save-dev 

В файле config/config.json добавьте следующую запись к свойству externals :

"angular": < "path": "https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.5.8/angular.min.js", "globalName": "angular" >

Весь файл config/config.json будет выглядеть примерно так:

 < "entries": [ < "entry": "./lib/webparts/helloWorld/HelloWorldWebPart.js", "manifest": "./src/webparts/helloWorld/HelloWorldWebPart.manifest.json", "outputPath": "./dist/hello-world.bundle.js" >], "externals": < "angular": < "path": "https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.5.8/angular.min.js", "globalName": "angular" >>, "localizedResources": < "helloWorldStrings": "webparts/helloWorld/loc/.js" >> 

Необходимо сослаться на Angular в веб-части:

import < Version >from '@microsoft/sp-core-library'; import < BaseClientSideWebPart, IPropertyPaneConfiguration, PropertyPaneTextField >from '@microsoft/sp-webpart-base'; import < escape >from '@microsoft/sp-lodash-subset'; import styles from './HelloWorld.module.scss'; import * as strings from 'helloWorldStrings'; import < IHelloWorldWebPartProps >from './IHelloWorldWebPartProps'; import * as angular from 'angular'; export default class HelloWorldWebPart extends BaseClientSideWebPart `; angular.module('helloworld', []); angular.bootstrap(this.domElement, ['helloworld']); > // omitted for brevity > 

Если вы выполните сборку проекта сейчас, размер созданного пакета составит всего 6 КБ.

Снимок экрана: проводник с изображением папки развертывания с выделенным файлом JavaScript Hello Word.

Если вы добавите в проект еще одну веб-часть на Angular и выполните сборку проекта, размер каждого пакета составит 6 КБ.

Снимок экрана: проводник с изображением папки развертывания с двумя выделенными файлами JavaScript Hello Word.

Неправильно считать, что вы сэкономили более 300 КБ. Обеим веб-частям по-прежнему нужен Angular, и он будет загружен, когда пользователь перейдет на страницу с одной из веб-частей.

Angular, выделенный в средствах разработчика, для страницы с одной веб-частью

Даже если вы добавите на страницу обе веб-части Angular, SharePoint Framework скачает Angular только один раз.

Angular, выделенный в средствах разработчика, для страницы с двумя веб-частями

Ссылаться на существующие библиотеки JavaScript как внешние ресурсы особенно удобно, если ваша организация хранит все распространенные сценарии вместе или вы используете CDN. В таком случае определенная библиотека JavaScript может уже быть в кэше браузера пользователя. В результате нужно загрузить только пакет веб-части, что ускоряет загрузку страницы.

На вкладке средств разработчика

В предыдущем примере показано, как загрузить Angular из сети CDN, но использовать общедоступную сеть CDN не обязательно. В конфигурации можно указать любое расположение: общедоступную сеть CDN, частный репозиторий или библиотеку документов SharePoint. Для нормальной работы веб-частей необходимо, чтобы у пользователей был доступ к указанным URL-адресам.

Сети CDN оптимизированы для быстрой доставки ресурсов по всему миру. Преимущество общедоступных сетей CDN также в том, что определенный сценарий уже мог использоваться на другом веб-сайте, который посещал пользователь. Так как сценарий уже есть в локальном кэше браузера, его не нужно скачивать специально для веб-части, поэтому страница с веб-частью будет загружаться еще быстрее.

В некоторых организациях запрещен доступ к общедоступным CDN из корпоративной сети. В таких случаях распространенные платформы JavaScript можно хранить в частном репозитории. Так как библиотеки размещаются в вашей организации, вы сможете управлять заголовками кэша, чтобы повысить скорость загрузки ресурсов.

Форматы библиотек JavaScript

Разные библиотеки JavaScript создаются и упаковываются по-разному. Одни упаковываются как модули, а другие представляют собой простые сценарии, которые выполняются в глобальной области (их часто называют немодульными сценариями). При загрузке библиотек JavaScript с URL-адреса порядок регистрации внешнего сценария в проекте SharePoint Framework зависит от его формата. Существует несколько форматов модулей (AMD, UMD, CommonJS), но вам достаточно знать, является ли сценарий модулем.

При регистрации сценариев, упакованных в виде модулей, вам нужно лишь указать URL-адрес для скачивания сценария. Зависимости от других сценариев загружены в конструкцию модуля сценария.

Для немодульных сценариев необходимо указать по крайней мере URL-адрес для скачивания сценария и имя переменной для регистрации в глобальной области. Если немодульный сценарий зависит от других сценариев, их можно указать как зависимости. Рассмотрим несколько примеров.

Angular 1.x — это немодульный сценарий. Чтобы зарегистрировать его как внешний ресурс в проекте SharePoint Framework, необходимо указать его URL-адрес и имя глобальной переменной для регистрации:

"angular": < "path": "https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.5.8/angular.min.js", "globalName": "angular" >

Важно, чтобы имя, указанное в свойстве globalName , соответствовало имени, используемому скриптом. В этом случае другие сценарии, которые от него зависят, смогут получить к нему доступ.

ngOfficeUIFabric — директивы Angular для Office UI Fabric. Это модуль UMD, который зависит от Angular. Зависимость от Angular уже загружена в модуль, поэтому для его регистрации вам нужно лишь указать его URL-адрес:

"ng-office-ui-fabric": "https://cdnjs.cloudflare.com/ajax/libs/ngOfficeUiFabric/0.12.3/ngOfficeUiFabric.js" 

jQuery — это сценарий AMD. Вот как его можно зарегистрировать:

"jquery": "https://code.jquery.com/jquery-2.2.4.js" 

Теперь представим, что вы хотите использовать jQuery с подключаемым модулем jQuery, который распространяется как немодульный сценарий.

Если вы зарегистрировали оба сценария, используя приведенный ниже код, загрузка веб-части, скорее всего, приведет к ошибке. Возможно, оба сценария будут загружаться параллельно и подключаемый модуль не сможет зарегистрироваться в jQuery.

"jquery": "https://code.jquery.com/jquery-2.2.4.js", "simpleWeather": < "path": "https://cdnjs.cloudflare.com/ajax/libs/jquery.simpleWeather/3.1.0/jquery.simpleWeather.min.js", "globalName": "jQuery" >

Сообщение об ошибке при загрузке веб-части с помощью немодульного подключаемого модуля jQuery

Как упоминалось ранее, платформа SharePoint Framework позволяет указать зависимости для немодульных подключаемых модулей. Эти зависимости задаются с помощью свойства globalDependencies :

"jquery": "https://code.jquery.com/jquery-2.2.4.js", "simpleWeather": < "path": "https://cdnjs.cloudflare.com/ajax/libs/jquery.simpleWeather/3.1.0/jquery.simpleWeather.min.js", "globalName": "jQuery", "globalDependencies": [ "jquery" ] >

Каждая зависимость, указанная в свойстве globalDependencies , должна указывать на другую зависимость в разделе externals файла config/config.json.

Теперь при сборке проекта появится другое сообщение об ошибке, в котором будет указано, что невозможно задать зависимость от немодульного сценария.

Ошибка при сборке проекта SharePoint Framework с зависимостью немодульного сценария от модульного

Чтобы устранить эту проблему, достаточно зарегистрировать jQuery как немодульный сценарий.

"jquery": < "path": "https://code.jquery.com/jquery-2.1.1.min.js", "globalName": "jQuery" >, "simpleWeather": < "path": "https://cdnjs.cloudflare.com/ajax/libs/jquery.simpleWeather/3.1.0/jquery.simpleWeather.min.js", "globalName": "jQuery", "globalDependencies": [ "jquery" ] >

Так вы укажите, что сценарий simpleWeather необходимо загружать после сценария jQuery, который должен быть доступен под глобально доступной переменной jQuery , необходимой для регистрации подключаемого модуля jQuery simpleWeather.

Обратите внимание, что запись для регистрации jQuery использует jquery для имени внешнего ресурса, но jQuery в качестве имени глобальной переменной. Имя внешнего ресурса — это имя, используемое import в инструкциях в коде. Это также имя, которое должно соответствовать объявлениям типов TypeScript. Имя глобальной переменной, заданное globalName с помощью свойства, — это имя, известное другим скриптам, например подключаемым модулям, встроенным поверх библиотеки. Хотя для некоторых библиотек эти имена могут быть одинаковыми, они не требуются, и вам следует тщательно проверить, используются ли правильные имена, чтобы избежать проблем.

Трудно вручную определить, является ли скрипт, который вы пытаетесь загрузить, модулем или немодулем. особенно если он минифицирован. Если ваш сценарий размещен по общедоступному URL-адресу, вы можете использовать бесплатный инструмент Rencore SharePoint Framework Script Check, чтобы автоматически определить тип сценария. Кроме того, этот инструмент позволяет узнать, правильно ли настроен место размещения, с которого загружается сценарий.

Рекомендации в отношении немодульных сценариев

Многие из разработанных ранее библиотек и сценариев JavaScript распространяются в виде немодульных сценариев. На платформе SharePoint Framework можно загружать немодульные сценарии, но лучше их не использовать.

Скрипты, не относящиеся к модулям, регистрируются в глобальной области страницы: скрипт, загруженный одной веб-частью, доступен для всех остальных веб-частей на странице. Если у вас есть две веб-части, использующие разные версии jQuery, которые загружаются как скрипты, не относящиеся к модулю, веб-часть, загружающая последнюю, перезаписывает все ранее зарегистрированные версии jQuery.

Как вы понимаете, результаты будут непредсказуемыми. Трудно отслеживать ошибки, возникающие только в определенных ситуациях (например, когда другие веб-части на странице используют другую версию jQuery и загружаются в определенном порядке). Для решения этой проблемы созданы модули: в них сценарии изолируются и не могут влиять друг на друга.

Рекомендации по объединению

Объединение существующих библиотек JavaScript в веб-часть может привести к возникновению больших файлов веб-частей и снижению производительности страниц, использующих эту веб-часть. Как правило, не следует объединять библиотеки JavaScript с веб-частями, но иногда это может быть полезно.

Если вы создаете стандартное решение, которое должно работать во всех интрасетях, объединение всех ресурсов с веб-частью может помочь обеспечить ее должную работу. Так как вы не знаете заранее, где будет установлено ваше решение, добавление всех зависимостей в пакет веб-части обеспечит ее правильную работу, даже если в организации запрещено скачивать ресурсы из сети CDN или другого внешнего источника.

Если решение состоит из нескольких веб-частей с общими функциями, лучше всего создать общие функции как отдельную библиотеку и сослаться на нее как внешний ресурс во всех веб-частях. В этом случае пользователям нужно всего один раз скачать общую библиотеку и использовать ее со всеми веб-частями.

Сводка

Для создания клиентских веб-частей на платформе SharePoint Framework можно использовать имеющиеся библиотеки JavaScript. Платформа SharePoint Framework позволяет объединять эти библиотеки вместе с веб-частями или загружать их как внешний ресурс. Мы рекомендуем загружать существующие библиотеки с URL-адреса, но иногда можно объединить их в пакет. Оцените свои потребности, чтобы выбрать наиболее подходящий способ.

См. также

Использование кэширования для повышения производительности

При доставке элементов контента, цифровых активов и сайтов следует использовать все преимущества кэша браузера посетителя для повышения производительности доставки и рендеринга контента в браузере.

Сайты, темы, элементы контента и цифровые активы кэшируются в кэше браузера посетителя на некоторое время. После обновления сайта, темы, элемента контента или цифрового актива ключ сброса кэша в URL-адресе изменяется, чтобы браузер мог извлечь другой URL-адрес и получить новый элемент.

Ключ кэша помогает управлять использованием кэша браузера путем формированию ссылок только на текущие ресурсы. Хотя ключ кэша включен в URL-адрес, он представляет собой логический элемент, а не физическое местоположение (папку), как это часто бывает. Изменение ключа кэша не указывает на необходимость поиска ресурса в другом физическом местоположении; оно просто уведомляет сервер о необходимости извлечения текущей версии ресурса.

Ресурсы могут быть статическими, такими как CSS, JS и файлы изображений, или динамическими, такими как данные страниц, сайта и элементов контента. При построении веб-сайта используются пять категорий ресурсов:

  • Ресурсы продуктов — это ресурсы, входящие в состав продукта, которые обновляются при выпуске или исправлении новой версии продукта.
  • Ресурсы сайта — это ресурсы, которые входят в состав сайта, такие как файл structure.json , данные страницы и изображения. Они обновляются при публикации сайта. Контроллер описан ниже.
  • Ресурсы тем — это ресурсы, входящие входят в состав тем, такие как макеты, CSS и изображения. Они обновляются при публикации темы.
  • Ресурсы компонентов — это ресурсы, входят в состав пользовательских компонентов. К ним относятся файлы HTML, JS и CSS, а также файлы изображений, из которых состоит компонент. Они обновляются при публикации компонента. Если один компонент изменяется и повторно публикуется, то ключ кэша изменяется для всех компонентов, так как это единственный ключ для всех компонентов.
  • Ресурсы CaaS — это ресурсы, обслуживающие элементы контента и цифровые элементы. Они обновляются при публикации или повторной публикации элементов контента или при изменении целевого объекта коллекции.

В последующих разделах описывается кэширование для среды выполнения Oracle Content Management и Site Builder.

  • Кэширование времени выполнения
  • Кэширование в Site Builder

Кэширование времени выполнения

Для времени выполнения заголовок Oracle Content Management Cache-Control задается на 15 дней. В URL-адрес всех ресурсов добавляется ключ кэша.

В случае совпадения URL-адреса браузер обслуживает ресурс из локального кэша, если это доступно. При обновлении ресурса ключ кэша обновляется в URL-адресе, что заставляет браузер отправить серверу новый запрос и обновить локальный кэш.

Контроллер с ключами кэша также кэшируется на 1 минуту. Поэтому обновленные ключи кэша не отображаются в течение 1 минуты.

Во время выполнения сервер возвращает controller.html с последними ключами кэша для ресурсов продукта, сайта, темы, компонентов и CaaS. В файл controller.html добавляется сценарий с ключами; например:

Эти ключи используются сценарием controller.js для построения URL-адресов, подобных тем, что описаны в следующей таблице.

/sitePrefix/productCacheKey/_sitesclouddelivery/.
/mySite/_cache_947d/_sitesclouddelivery/
/sitePrefix/themeCacheKey/_themesdelivery/themeName/.
/sitePrefix/compCacheKey/_compdelivery/compName/.
/sitePrefix/siteCacheKey/content/. /sitePrefix/siteCacheKey/structure.json /sitePrefix/siteCacheKey/pages/100.json
RegularCaaSUrl?cacheKey=caasCacheKey

Вставляя ключ кэша в URL-адреса, подобные этому, Oracle Content Management может заставить браузер загружать обновленные ресурсы, фактически изменив URL-адрес, чтобы браузер считал, что это новый ресурс.

Для безопасных сайтов кэшируются только ресурсы продукта, темы и компонента, а не контент сайта или CaaS.

Кэширование в Site Builder

В Site Builder статические ресурсы кэшируются на 15 дней.

При использовании Site Builder кэшируются ресурсы продукта, темы и компонентов. (Это не происходит для ресурсов сайтов и CaaS.) При запуске или обновлении Site Builder ключи кэша темы и компонентов создаются заново.

Если внести изменения в тему или компонент и требуется, чтобы изменения отображались в Site Builder, необходимо обновить Site Builder (F5).

Добавление внешней библиотеки в клиентскую веб-часть SharePoint

Вам может понадобиться добавить в веб-часть одну или несколько библиотек JavaScript. В этой статье описано, как добавить внешнюю библиотеку в пакет и использовать библиотеки в нескольких веб-частях.

Добавление сценария в пакет

По умолчанию средство увязки веб-частей в пакеты автоматически добавляет библиотеки, которые представляют собой зависимости для модуля веб-части. Это означает, что такие библиотеки развертываются в том же файле пакета JavaScript, что и веб-часть. Это удобно в случае небольших библиотек, которые не используются в нескольких веб-частях.

Пример
  1. Добавьте библиотеку проверки строк в веб-часть.
  2. Скачайте пакет средств проверки, используя NPM:
npm install validator --save 

Примечание. Так как вы используете TypeScript, скорее всего, вам понадобятся объявления типов для добавляемого пакета. Это полезно при написании кода, так как TypeScript — это просто надмножество JavaScript. Весь код TypeScript по-прежнему преобразуется в код JavaScript при компиляции. Объявления типов можно установить с помощью NPM, например npm install @types/ —save-dev.

declare module "validator"

Примечание. Для некоторых библиотек нет объявлений типов. Хотя в библиотеке проверки имеется созданный сообществом файл объявлений типов, но для этого сценария предположим, что его нет. В этом случае нужно задать собственный файл определений объявлений типов .d.ts для библиотеки. Ниже приведен пример.

import * as validator from 'validator'; 
validator.isEmail('someone@example.com'); 

Использование библиотеки несколькими веб-частями

Клиентское решение может включать несколько веб-частей. Для них может потребоваться импортировать или использовать одну и ту же библиотеку. В таких случаях не добавляйте библиотеку в пакет, а включите ее в отдельный файл JavaScript, чтобы повысить эффективность и улучшить кэширование. Особенно это касается больших библиотек.

Пример

В этом примере пакет marked (компилятор markdown) помещается в отдельный пакет для совместного использования.

    Скачайте пакет marked с помощью NPM:

npm install marked --save 
npm install @types/marked --save-dev 
"marked": "node_modules/marked/marked.min.js" 
import * as marked from 'marked'; 
console.log(marked('I am using __markdown__.')); 

Загрузка сценария из сети CDN

Вы можете не загружать библиотеку из пакета NPM, а загрузить сценарий из сети доставки содержимого (CDN). Для этого измените файл config.json, чтобы обеспечить загрузку библиотеки с использованием URL-адреса CDN.

Пример

В этом примере вы загрузите jQuery из CDN. Вам не нужно устанавливать пакет NPM. Однако по-прежнему необходимо установить объявления типов.

    Установка объявлений типов для jQuery:

npm install --save-dev @types/jquery 
"jquery": "https://code.jquery.com/jquery-3.1.0.min.js" 
import * as $ from 'jquery'; 
alert( $('#foo').val() ); 

Загрузка модуля, отличного от AMD-модуля

Некоторые скрипты следуют устаревшей схеме JavaScript хранения библиотеки в глобальном пространстве имен. Этот шаблон теперь не рекомендуется использовать в пользу универсальных определений модулей (UMD)/асинхронных определений модулей (AMD) или модулей ES6. Однако может потребоваться загрузить такие библиотеки в веб-части.

Трудно определить вручную, является ли загружаемый сценарий сценарием AMD, особенно если он минифицирован.

Если ваш сценарий размещен по общедоступному URL-адресу, вы можете использовать бесплатный инструмент Rencore SharePoint Framework Script Check, чтобы автоматически определить тип сценария. Кроме того, этот инструмент позволяет узнать, правильно ли настроен место размещения, с которого загружается сценарий. Этот инструмент также доступен в расширении VS Code Rencore SPFx Script Check

Чтобы загрузить модуль, созданный не с помощью AMD, добавьте дополнительное свойство в запись в файле config.json.

Пример

В этом примере вы загрузите вымышленный модуль, отличный от AMD, из сети CDN Компании Contoso. Эти действия применяются для любого сценария, отличного от AMD, в каталоге src/ или node_modules/.

Скрипт называется Contoso.js и хранится в https://contoso.com/contoso.js. Его содержимое:

var ContosoJS = < say: function(text) < alert(text); >, sayHello: function(name) < alert('Hello, ' + name + '!'); >>; 
  1. Создайте объявления типов для сценария в файле contoso.d.ts в папке веб-части.
declare module "contoso" < interface IContoso < say(text: string): void; sayHello(name: string): void; >var contoso: IContoso; export = contoso; > 
import contoso from 'contoso'; 
contoso.sayHello(username); 

Загрузка библиотеки с зависимостью от другой библиотеки

Многие библиотеки содержат зависимости от другой библиотеки. Такие зависимости можно указать в файле config.json с помощью свойства globalDependencies .

Обратите внимание, что это поле не нужно указывать для AMD-модулей. Они импортируют друг друга правильно. Однако AMD-модуль не может зависеть от модуля, отличного от AMD. В некоторых случаях можно загрузить сценарий AMD в виде сценария, отличного от AMD. Это часто требуется при работе с библиотекой jQuery, которая сама по себе является сценарием AMD, и подключаемыми модулями jQuery, которые в большинстве случаев распространяются как сценарии, отличные от AMD, и зависят от jQuery.

Ниже приведены два примера.

Для модуля, отличного от AMD-модуля, предусмотрена соответствующая зависимость

В этом примере используются два вымышленных сценария. Они хранятся в папке src/, но их также можно загрузить из CDN.

ContosoUI.js

Contoso.EventList = < alert: function() < var events = Contoso.getEvents(); events.forEach( function(event) < alert(event); >); > > 

ContosoCore.js

var Contoso = < getEvents: function() < return ['A', 'B', 'C']; >>; 
  1. Добавление или создание объявлений типов для этого класса. В этом случае вы создадите Contoso.d.ts, который содержит объявления типов для обоих файлов JavaScript. contoso.d.ts
declare module "contoso" < interface IEventList < alert(): void; >interface IContoso < getEvents(): string[]; EventList: IEventList; >var contoso: IContoso; export = contoso; > 
< "contoso": < "path": "/src/ContosoCore.js", "globalName": "Contoso" >, "contoso-ui": < "path": "/src/ContosoUI.js", "globalName": "Contoso", "globalDependencies": ["contoso"] >> 
import contoso = require('contoso'); require('contoso-ui'); 
contoso.EventList.alert(); 

Загрузка JSOM SharePoint

Модели JSOM SharePoint загружаются практически так же, как сценарии с зависимостями, отличные от AMD-сценариев. Это означает использование globalName параметров и globalDependency .

Обратите внимание, что приведенный ниже подход вызовет ошибки на классических страницах SharePoint, где модель JSOM уже загружена. Если ваша веб-часть должна работать как с классическими, так и современными страницами, нужно сначала проверить, доступна ли модель JSOM, а если нет, загрузить ее динамически с помощью SPComponentLoader.

  1. Установите объявления типов для Microsoft Ajax, которые являются зависимостью для объявлений типов JSOM:
npm install @types/microsoft-ajax --save-dev 
npm install @types/sharepoint --save-dev 
< "sp-init": < "path": "https://CONTOSO.sharepoint.com/_layouts/15/init.js", "globalName": "$_global_init" >, "microsoft-ajax": < "path": "https://CONTOSO.sharepoint.com/_layouts/15/MicrosoftAjax.js", "globalName": "Sys", "globalDependencies": [ "sp-init" ] >, "sp-runtime": < "path": "https://CONTOSO.sharepoint.com/_layouts/15/SP.Runtime.js", "globalName": "SP", "globalDependencies": [ "microsoft-ajax" ] >, "sharepoint": < "path": "https://CONTOSO.sharepoint.com/_layouts/15/SP.js", "globalName": "SP", "globalDependencies": [ "sp-runtime" ] >> 
require('sp-init'); require('microsoft-ajax'); require('sp-runtime'); require('sharepoint'); 

Загрузка локализованных ресурсов

В файле config.json вы можете использовать схему localizedResources , чтобы описать принцип загрузки локализованных ресурсов. Пути в этой схеме заданы относительно папки lib и не должны содержать начальную косую черту (/).

В этом примере у вас есть папка src/strings/. В этой папке есть несколько файлов JavaScript с такими именами, как en-us.js, fr-fr.js ,de-de.js. Так как каждый из этих файлов должен загружаться загрузчиком модулей, они должны содержать оберточный код CommonJS. Например, в случае файла en-us.js:

define([], function() < return < "PropertyPaneDescription": "Description", "BasicGroupName": "Group Name", "DescriptionFieldLabel": "Description Field" >>); 
  1. Измените файл config.json. Добавьте запись в localizedResources . — это замещающий токен для имени языкового стандарта.
declare interface IStrings < webpartTitle: string; initialPrompt: string; exitPrompt: string; >declare module 'mystrings'
import * as strings from 'mystrings'; 
alert(strings.initialPrompt); 

См. также

Избежать проблемы с кешем при использовании import | JS

Данные решения меня не устраивают. Первый в силу своей костыльности, а второй в силу ручного рукоблудства при изменении содержимого скрипта (доступа к .htaccess у меня нет).

Отслеживать
ComeInRage
задан 12 сен 2021 в 14:29
ComeInRage ComeInRage
1,590 6 6 серебряных знаков 14 14 бронзовых знаков
Можете использовать webpack, он сам всё переименует.
12 сен 2021 в 15:13

@nazarpunk мне кажется, что это неплохой совет. Однако есть ли способы делать это на чистом JS без сторонних подключений и, желательно, jQuery?

12 сен 2021 в 15:23

если на сервере настроен ETag то вообще ничего делать не нужно, всё само прекрасно работает. Если вы конечно не кешируете через ServiceWorker, там свои ньюансы есть. Использование jQuery в 2021 выглядит сомнительно. А на чистом js вы это не решите. Если не хотите использовать webpack, то можете посмотреть в сторону gulp.

12 сен 2021 в 20:13

@nazarpunk проблема в том, что у меня доступ только к части файловой системы сайта и все. Даже доступа к основному .htaccess нет. Не говоря уже о настройках сервера, так что webpack я не могу поставить, увы. Однако это хороший вариант и я возьму его на заметку, если в будущем столкнусь с этой проблемой

13 сен 2021 в 11:01

Так webpack и gulp нужен только для разработчиков и на сервер не ставится. Основная идея сформировать файлы и залить их на сервер.

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *