How to use ES6 import” with Chrome Extension

Oct 28, 2018 · 2 min read

Expecting JavaScript developers who have / will have developed Chrome Extension ever.


The minimum example is working here.

Table of Contents

  1. Why?


Static files like CSS and JavaScript always have a specific problem to deliver themselves: “How to bundle bunch of dependencies to one file”.

For JavaScript, as you know, there are many bundler middleware, e.g. Browserify, RequireJS and Webpack, can resolve “require” method or “import” keyword and bundle JavaScript (sometimes AltJS) files to a single output.

Thanks to browsers’ support of ES2015 (so called ES6), “import” keyword can be used without using such middleware mentioned above, only when you add type="module" to your <script> tag.

<script type="module" src="your-script.js"></script>

OK, then, can we use module importing with developing Chrome Extension, with which JavaScript is loaded by manifest.json ?

Background Script

Since background script of Chrome Extension is loaded by background.scripts field of manifest.json , it’s not possible to add “module” attribute as <script> tag. So just let’s use field instead, as an entrypoint of your JavaScript files.

    "background": {
        "page": "src/html/background.html"

then src/html/background.html looks like

<script type="module" src="src/js/background.js"></script>

It works fine 👍

Content Script

Content Script, on the other hand, must be loaded automatically when content_scripts are specified in manifest.json, kind of hacks are needed.

If import keyword simply appears on one of content_scripts, following error message comes up.

Uncaught SyntaxError: Unexpected identifier

This is because it’s loaded without type="module" attribute. We, somehow, kick our JavaScript by <script> tag with type="module", at least the entrypoint of it.

The idea is to use dynamic import which is equivalent to add type="module" to the dynamically imported script.

The content_script would look like

(async () => {
  const src = chrome.extension.getURL('src/js/main.js');
  const contentScript = await import(src);

Once it’s imported by dynamic import, import keyword can be used just as it’s loaded with type="module".

src/js/main.js can be like this

import User from "./my-models/User";export function main() {
  // Do what you want
  const user = new User({name: "otiai10"});

Alternatively, injecting script tag by content_script (introduced in this thread) can kick other JavaScript files with type="module", but as it’s external script for Chrome Extension Lifecycle, chrome namespace can be eliminated and it requires some hack to use chrome, e.g. dependency injection.


Thus, it’s not so hard work to use import for your Chrome Extension. But still we have problems which are usually solved by kind of Webpack.

  1. How to solve node_modules and sub dependencies inside them?

We can take more benefits by using such middleware with well-structured functionalities. I decided to leave native import keywords for now.


2 claps

Written by

wanna be died on Mars