lilotop
lilotop

Reputation: 577

How can I create a Vuetify based browser extension?

I'm using the Vue CLI UI.
I've created a project and added the vue-cli-plugin-browser-extension

So far so good.

Now I'm trying to add Vuetify into the mix.
I tried with the official plugin, but nothing shows up in the extension's popup.
I tried the CDN approach but when I try to add Vuetify to the Vue instance I get an error saying Vuetify is not defined.

Any Ideas?

Also important: I would really much prefer not to use the CDN approach if it is at all possible. Is there a way to use npm install to also install the css and fonts needed to run Vuetify?

Upvotes: 4

Views: 2363

Answers (5)

Talal
Talal

Reputation: 424

for any one wants complete local build without any cdns

already has Vue + Vuetify + Material Design Icons

i made this repo which originally cloned from Kocal/vue-web-extension's repo

https://github.com/talal424/chrome-extension-vue-vuetify/

clone the repo then install the dependencies and build

npm i

# for production
npm run build

# for development ( there is no HMR )
npm run dev

you can load the extension unpacked from the folder /dist/

edit webpack.config.js to add more entry points

edit /src/popup/popup.js to add vuex or vue-router

the manifest file is /src/manifest.json which will be copied to the dist folder after build

Upvotes: 1

Johan Hoeksma
Johan Hoeksma

Reputation: 3746

If you want an offline version:

vue create my-app
cd my-app
vue add vuetify

Then you answer the questions:

Choose a preset: 
> Configure (advanced)

Use fonts as a dependency (for Electron or offline)? 
> Yes

I think this is a good way, without writing any code.

Upvotes: 1

Tony O'Hagan
Tony O'Hagan

Reputation: 22692

Another option would be to switch to Vue / Quasar framework that includes support for creating browser extensions...

https://quasar.dev/quasar-cli/developing-browser-extensions/introduction

Upvotes: 0

Juraj
Juraj

Reputation: 6598

regarding the hard part (point 4), here is what you can do.

First of all, make sure your Webpack can load css files (I think you need mini-css-extract-plugin for that).

Then simply import Vuetify and Material design icons using:

import 'vuetify/dist/vuetify.min.css';
import 'material-design-icons-iconfont/dist/material-design-icons.css';
// or if you like FontAwesome:
import '@fortawesome/fontawesome-free/css/all.css';

That's the easy part. Now to get the Roboto font you need to download the font styles https://fonts.googleapis.com/css?family=Roboto:100,300,400,500,700,900 and for each font inside download it and replace the url path with local path. To do this I've wrote simple script that can be executed with Node:

const fetch = require("node-fetch");
const fs = require("fs");
const mkdirp = require('mkdirp');

const fontDirPath = './fonts/Roboto';
mkdirp.sync(fontDirPath);

(async () => {
  const text = await (await fetch('https://fonts.googleapis.com/css?family=Roboto:100,300,400,500,700,900', {
    headers: {
      // we need to supply user-agent header because Google will return different (insufficient) response without it
      'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:78.0) Gecko/20100101 Firefox/78.0',
    }
  })).text()

  const fontCss = text
    .split('\n')
    .map(line => {
      const hasURL = line.includes('url(https');
      const [, url, fileName] = line.match(new RegExp('(https://.*/(.*.woff2))\\)')) || [];
      if (hasURL) downloadFile(url, `${fontDirPath}/${fileName}`);
      return hasURL ?
        line.replace(url, fileName):
        line;
    })
    .join('\n');
  fs.writeFileSync(`${fontDirPath}/font_roboto.css`, Buffer.from(fontCss, 'utf-8'));
})()

async function downloadFile(url, path) {
  const res = await fetch(url);
  const fileStream = fs.createWriteStream(path);
  await new Promise((resolve, reject) => {
    res.body.pipe(fileStream);
    res.body.on('error', reject);
    fileStream.on('finish', resolve);
  });
}

The scripts could be improved, right now it looks for only "woff2" fonts.

After that import your downloaded and edited CSS file:

import './fonts/Roboto/font_roboto.css';

Upvotes: 1

lilotop
lilotop

Reputation: 577

NPM Solution (with css and fonts brought in using CDN)

Got it!
It's not that hard after all but you need to pay attention to the differences between a regular app and a browser extension created by the Vue plugin.

The main differences are:

  1. Each part of the extension (popup, options, tab, etc.) is a completely new and isolated Vue App.
  2. The html template used for the extension parts is not public/index.html

Instructions:

  1. Create the project as instructed in the OP above.
  2. Install the Vuetify npm package: npm install vuetify
  3. In each main.js of each part you intend to use, add Vuetify:
    import Vue from 'vue'
    import App from './App.vue'

    import Vuetify from "vuetify";

    Vue.use(Vuetify);

    new Vue({
      el: '#app',
      vuetify: new Vuetify(),
      render: h => h(App)
    });
  1. Now look for the file public/browser-extension.html and add these lines in the header section:
  <link href="https://fonts.googleapis.com/css?family=Roboto:100,300,400,500,700,900" rel="stylesheet">
  <link href="https://cdn.jsdelivr.net/npm/@mdi/[email protected]/css/materialdesignicons.min.css" rel="stylesheet">
  <link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Material+Icons">
  <link href="https://cdn.jsdelivr.net/npm/[email protected]/dist/vuetify.min.css" rel="stylesheet">

That's it!

If you have an idea on how to convert item #4 into an npm variant, please share.

Upvotes: 1

Related Questions