chrome浏览器插件开发实践

前言

参考:
https://www.cnblogs.com/liuxi...
https://developer.chrome.com/...
使用Vue.js开发一个简单的文档阅读辅助插件,效果如下:
折叠api菜单
api_collapse.gif
笔记
notes.gif
嵌入代码
css.gif

脚手架搭建

安装依赖

npm i @babel/core @babel/plugin-transform-runtime @babel/preset-env @babel/runtime babel-loader autoprefixer postcss postcss-loader babel-plugin-component copy-webpack-plugin css-loader file-loader html-webpack-plugin node-sass sass-loader style-loader url-loader vue-loader vue-template-compiler webpack webpack-cli -D
npm i element-ui mavon-editor vue -S

新建webpack.config.js文件:

const path = require('path')
const CopyWebpackPlugin = require('copy-webpack-plugin')
const HTMLWebpackPlugin = require('html-webpack-plugin')
const VueLoaderPlugin = require('vue-loader/lib/plugin')

const mode = process.env.NODE_ENV.trim()

module.exports = {
  mode,
  entry: {
    content: './src/content/index.js',
    popup: './src/popup/index.js',
    options: './src/options/index.js',
    background: './src/background/index.js'
  },
  output: {
    filename: '[name]/[name].js',
    path: path.resolve('dist'),
    publicPath: './'
  },
  resolve: {
    modules: [
      'node_modules'
    ],
    extensions: ['.vue', '.js', '.json'],
    alias: {
      'vue$': 'vue/dist/vue.js'
    }
  },
  module: {
    rules: [
      {
        test: /\.scss$/,
        use: [
          'style-loader',
          'css-loader',
          'sass-loader',
          'postcss-loader'
        ]
      },
      {
        test: /\.css$/,
        use: [
          {
            loader: 'style-loader',
            options: {
              insert: 'html',
            }
          },
          'css-loader'
        ]
      },
      {
        test: /\.js$/,
        loader: 'babel-loader'
      },
      {
        test: /\.vue$/,
        loader: 'vue-loader'
      },
      {
        test: /\.(eot|svg|ttf|woff|woff2)(\?\S*)?$/,
        loader: 'url-loader'
      }
    ]
  },
  plugins: [
    new HTMLWebpackPlugin({
      template: './src/popup/index.html',
      filename: 'popup.html',
      chunks: ['popup']
    }),
    new HTMLWebpackPlugin({
      template: './src/options/index.html',
      filename: 'options.html',
      chunks: ['options']
    }),
    new CopyWebpackPlugin({
      // root is output(dist)
      patterns: [
        {
          from: 'manifest.json',
          to: '.'
        },
        {
          from: 'src/static',
          to: 'static'
        }
      ]
    }),
    new VueLoaderPlugin()
  ]
}

新建.babelrc文件:

{
  "presets": [
    [
      "@babel/preset-env",
      {
          "targets": {
            "chrome": "58",
            "ie": "8"
          },
          "modules": false
      }
    ]
  ],
  "plugins": [
    [
      "@babel/plugin-transform-runtime",
      {
        "helpers": false,
        "useESModules": true,
        "absoluteRuntime": true
      }
    ],
    [
      "component",
      {
        "libraryName": "element-ui",
        "styleLibraryName": "theme-chalk"
      }
    ]
  ]
}

新建postcss.config.js文件:

module.exports = {
  plugins: [
    require('autoprefixer')()
  ]
}

新建Manifest.json文件:

{
  "manifest_version": 2,
  "name": "web_docs_helper",
  "version": "1.0.0",
  "description": "",
  "permissions": [
    "storage",
    "tabs"
  ],
  "content_scripts": [
    {
      "matches": [
        "<all_urls>"
      ],
      "js": [
        "content/content.js"
      ],
      "run_at": "document_start"
    }
  ],
  "browser_action": {
    "default_title": "这是一个示例Chrome插件",
    "default_popup": "popup.html"
  },
  "options_ui": {
    "page": "options.html",
    "chrome_style": true
  },
  "background": {
    "script": "background/background.js"
  },
  "content_security_policy": "style-src 'self' 'unsafe-inline';script-src 'self' 'unsafe-eval' https://cdn.bootcss.com~~; object-src 'self' ;"
}

项目目录

新建src文件夹,对应页面看webpack.config.js的entry,现在用content来举例。
在src文件夹中新建:
image.png

在index.js中引入Vue:

import Vue from 'vue'
import VMenu from './menu'
import {Popover, Button, Input, Dialog, Card} from 'element-ui'
import mavonEditor from 'mavon-editor'
import 'mavon-editor/dist/css/index.css'

Vue.use(mavonEditor)
Vue.use(Popover)
Vue.use(Button)
Vue.use(Input)
Vue.use(Dialog)
Vue.use(Card)

let VApp

window.addEventListener('DOMContentLoaded', async () => {
  // 如果是禁用页面
  const isMatched = await isMatchedPage(window.location.href)
  if (!isMatched) return

  const el = document.createElement('div')
  el.id = 'v-app'
  document.body.appendChild(el)
  try {
    const items = await getChromeStorage({[isShowMenuKey]: true})
    VApp = new Vue({
      el: '#v-app',
      components: {
        VMenu
      },
      template: '<v-menu ref="menu" :isShowMenu="isShowMenu" @update:isShowMenu="setIsShowMenu" />',
      data: {
        isShowMenu: items[isShowMenuKey]
      },
      methods: {
        setIsShowMenu (value) {
          // some code here
        }
      }
    })
  } catch (err) {}
})

完整代码:
https://github.com/maoyonglon...

阅读 212

推荐阅读