Git Product home page Git Product logo

webextension-manifest-loader's Introduction

webextension-manifest-loader

npm version node version code style: prettier

Webpack loader that loads browser tailored manifest.json. It also imports all importable properties, allowing you to have 'manifest.json' as your only webpack entry point.

Use it together with inert-entry-webpack-plugin, spawn-loader, and maybe html-loader, more info below.

Table of Contents

Getting Started

To begin, you'll need to install webextension-manifest-loader:

npm install --save-dev webextension-manifest-loader

Then add the loader to your webpack config. For example:

webpack.config.js

module.exports = {
  module: {
    rules: [
      {
        // Prevent json-loader from loading the file
        type: 'javascript/auto',
        test: /manifest\.json$/,
        use: [
          // webextension-manifest-loader returns a function for importing in a .js file,
          // convert it to a plain string and resolve imports using extract-loader
          'extract-loader',
          {
            loader: 'webextension-manifest-loader',
            options: {
              // Use the environment variable TARGET_VENDOR as the target vendor
              targetVendor: process.env.TARGET_VENDOR,
              // Merge some properties into the finished manifest.json
              merge: {
                // This could easily come from an import of your package.json
                version: '1.3.0',
              },
            },
          },
        ],
      },
    ],
  },
};

Options

Name Type Default Description
targetVendor string undefined Specify the target vendor, should be one of firefox,chrome,edge,opera
merge Object {} Allows merging properties into the finished manifest.json

Example

See jsmnbom/ao3-enhancements (manifest.json, webpack.config.ts) for a fully featured example of using this loader together with typescript, vue (+vuetify) and pug.

Configuration

Make sure you're using inert-entry-webpack-plugin, otherwise webpack will try to output manifest.json as a javascript file, and that will obviously fail!

webpack.config.js (configuration)

module.exports = {
  entry: {
    manifest: './manifest.json',
  },
  module: {
    rules: [
      {
        // Prevent json-loader from loading the file
        type: 'javascript/auto',
        test: /manifest\.json$/,
        use: [
          // webextension-manifest-loader returns a function for importing in a .js file,
          // convert it to a plain string and resolve imports using extract-loader
          'extract-loader',
          {
            loader: 'webextension-manifest-loader',
            options: {
              // Use the environment variable TARGET_VENDOR as the target vendor
              targetVendor: process.env.TARGET_VENDOR,
              // Merge some properties into the finished manifest.json
              merge: {
                // This could easily come from an import of your package.json
                version: '1.3.0',
              },
            },
          },
        ],
      },
      {
        test: /\.html$/,
        use: [
          'file-loader?name=[path][name].html',
          'extract-loader',
          'html-loader',
        ],
      },
    ],
  },
  plugins: [new InertEntryPlugin()],
};

manifest.json (configuration)

Now you'll be able to specify vendors in your manifest.json keys and to import files.

{
  "manifest_version": 2,
  "version": "",
  "__firefox_icons__": {
    "48": "./icon.svg",
    "96": "./icon.svg"
  },
  "__chrome_icons__": {
    "48": "./icon-48.png",
    "96": "./icon-96.png"
  },
  "options_ui": {
    "page": "~spawn-loader?name=options_ui/index.html!./options_ui/index.html",
    "__firefox_browser_style__": false,
    "__chrome_chrome_style__": false
  },
  "content_scripts": [
    {
      "matches": [...],
      "__firefox_js__": [
        "~spawn-loader?name=content_script/index.js!./content_script/index.js"
      ],
      "__chrome_js__": [
        "~file-loader?name=[name].[ext]!webextension-polyfill/dist/browser-polyfill.min.js",
        "~spawn-loader?name=content_script/index.js!./content_script/index.js"
      ],
      "css": ["./content_script/style.css"]
    }
  ]
}

Here we import .svg if compiling for firefox, but .pngs if compiling for chrome since chrome doesn't support svgs in the icons property. We also add the webextension-polyfill on chrome but not on firefox as it's not needed there.

Use a loader like spawn-loader to add a new entry point. Remember to add a tilde in front of the loader or it will be resolved as a relative path.

Output if targetVendor == 'chrome'

Here's the output of the above configuration when run through webpack. And because we are using html-loader which can also resolve imports in <script> tags, again using spawn-loader we could include javascript files in our options_ui/index.html.

manifest.json (output)

{
  "manifest_version": 2,
  "version": "0.3.0",
  "icons": {
    "48": "/icon-48.png",
    "96": "/icon-96.png"
  },
  "options_ui": {
    "page": "/options_ui/index.html",
    "chrome_style": false,
    "open_in_tab": true
  },
  "content_scripts": [
    {
      "matches": [...],
      "js": [
        "/browser-polyfill.min.js",
        "/content_script/index.js"
      ],
      "css": [
        "/content_script/style.css"
      ],
      "run_at": "document_start"
    }
  ],
}

FAQ

Which properties does it currently support?

All properties can use the target vendor feature, but only some properties will be resolved by webpack. These are currently: (if you need more please open an issue or PR)

Please see the src/interfaces.ts -> Manifest interface for these currently supported properties.

Are there any known limitation or problems?

  • Does not resolve imports in localizable property values (ones starting with __MSG_).
  • Does not work with webpack's [hash], this should be okay as it's not really needed for webextensions.
  • Webpack doesn't display progress for child compilers (like spawn-loader) correctly.

Related and thanks

I wrote this loader mostly as a challange to myself to see if it could be done. It is heavily inspired by wext-manifest-loader, and uses parts from html-loader for the import mechanism.

webextension-manifest-loader's People

Contributors

jsmnbom avatar dependabot[bot] avatar

Stargazers

Ryan Ferris avatar Space avatar Martin Giger avatar Gabin Aureche avatar Bradley Walters avatar Abhijith Vijayan avatar Peter Thaleikis avatar

Watchers

James Cloos avatar  avatar

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.