Ожидается, что разработчики JavaScript, которые разработали / будут когда-либо разрабатывать расширения для Chrome.
tl;dr
Здесь работает минимальный пример.
Оглавление
- Почему?
- Фоновый скрипт
- Скрипт содержания
- Заключение
Почему?
Статические файлы, такие как CSS и JavaScript, всегда сталкиваются с определенной проблемой: «Как связать множество зависимостей в один файл».
Для JavaScript, как вы знаете, существует множество связующего ПО, например Browserify, RequireJS и Webpack могут разрешать метод require или ключевое слово import и объединять файлы JavaScript (иногда AltJS) в один вывод.
Благодаря поддержке браузерами ES2015 (так называемого ES6) ключевое слово «import» можно использовать без использования упомянутого выше промежуточного программного обеспечения, только когда вы добавляете type="module"
в свой тег <script>
.
<script type="module" src="your-script.js"></script>
Хорошо, тогда можем ли мы использовать импорт модулей при разработке расширения Chrome, с которым manifest.json
загружает JavaScript?
Фоновый скрипт
Поскольку фоновый скрипт расширения Chrome загружается из поля background.scripts
из manifest.json
, невозможно добавить атрибут «модуль» в качестве тега <script>
. Так что давайте вместо этого используем поле background.page
в качестве точки входа в ваши файлы JavaScript.
{ "background": { "page": "src/html/background.html" } }
тогда src/html/background.html
выглядит как
<script type="module" src="src/js/background.js"></script>
Работает нормально 👍
Скрипт содержимого
С другой стороны, Content Script должен загружаться автоматически, когда content_scripts
указаны в manifest.json
, необходимы какие-то хаки.
Если ключевое слово import
просто появляется в одном из content_scripts
, появляется следующее сообщение об ошибке.
Uncaught SyntaxError: Unexpected identifier
Это потому, что он загружен без атрибута type="module"
. Мы каким-то образом отбрасываем наш JavaScript тегом <script>
с type="module"
, по крайней мере, его точкой входа.
Идея состоит в том, чтобы использовать динамический импорт, который эквивалентен добавлению type="module"
к динамически импортируемому скрипту.
Content_script будет выглядеть как
(async () => { const src = chrome.extension.getURL('src/js/main.js'); const contentScript = await import(src); contentScript.main(); })();
После импорта с помощью динамического импорта ключевое слово import
можно использовать так же, как оно загружено с type="module"
.
ПРИМЕЧАНИЕ. Поскольку
import(src)
выполняется в контексте средства визуализации страницы, который находится вне расширения Chrome, вам может потребоваться сделатьsrc
доступным с веб-сайта с помощью директивы web_accessible_resources в вашемmanifest.json
.
src/js/main.js
может быть так
import User from "./my-models/User"; export function main() { // Do what you want const user = new User({name: "otiai10"}); console.log(user); }
В качестве альтернативы, внедрение тега сценария с помощью content_script (представленного в этом потоке) может отбросить другие файлы JavaScript с type="module"
, но, поскольку это внешний сценарий для жизненного цикла расширения Chrome, пространство имен chrome
может быть исключено, и для этого потребуется некоторый взлом для использования chrome
, например внедрение зависимости.
Заключение
Таким образом, использовать import
для расширения Chrome не так уж и сложно. Но все же у нас есть проблемы, которые обычно решаются с помощью Webpack.
- Как решить
node_modules
и подзависимости внутри них? - В некоторых случаях все еще требуется минификация / ускользание / транспиляция AltJS.
Мы можем получить больше преимуществ, используя такое промежуточное программное обеспечение с хорошо структурированными функциями. Я решил пока оставить нативные import
ключевые слова.