[webpack学习]以vue-cli的方式开发油猴脚本

3,508 阅读3分钟

为什么是油猴, 而不是Chrome插件?

开发浏览器插件主要有两条路子, 一个是chrome插件, 另一个就是油猴脚本了。油猴脚本是依附于TemperMonkey这个Chrome插件的跨浏览器脚本。

那我直接开发chrome插件不就好了?

Chrome插件需要经过google商店的审核才能发布, 审核流程非常麻烦, 而且要叫几刀来激活你的账号才能发布插件,还要涉及到墙的问题。即使你开发来自己使用,在未打包的状态下,每次打开浏览器都会弹窗提示风险信息,没法关闭。如果你打包发给朋友使用的话,Chrome会检测google商店中是否有这个插件,没有的话直接停用,没有任何操作空间,总之不上架商店寸步难行。当然了,Chrome插件可以调用google提供的api, 实现google账号同步数据等等骚操作。

油猴脚本开发起步

官方文档

创建一个新的脚本,包含如下代码:UserScript的headers注释;脚本代码。

// ==UserScript==
// @name         New Userscript
// @namespace    http://tampermonkey.net/
// @version      0.1
// @description  try to take over the world!
// @author       You
// @match        https://www.tampermonkey.net/documentation.php?version=4.10&ext=dhdg
// @grant        none
// ==/UserScript==

(function() {
    'use strict';
    // Your code here...
})();

通常,脚本发布平台都有如下规定,比如Greasy Fork:

提交到本站的代码不得混淆或压缩最小化,这包括使用 WebPack 这类打包工具处理后的脚本。用户必须能在安装之前对即将安装的脚本进行审阅并理解其作用。

由于脚本所有的逻辑都集成在一个js中,还不能用webpack构建,这意味着开发脚本的过程相当的原生,感觉回到了前端刀耕火种的年代,但正是这样,才能保证审核和脚本安全。

怀着学习的心态,我们还是试着使用webpack构建脚本,这样开发的脚本无法上传到代码平台,只能自己使用了

以类似于vue-cli的方式来开发油猴脚本

注意,这样开发的脚本无法上传到代码平台,仅适用于学习webpack配置或开发自用脚本

项目结构

|--dist // 构建位置
|--src
   |--main.js // 入口文件
   |--app.vue 
|--webpack.common.js // 通用配置
|--webpack.dev.js // 开发配置
|--webpack.prod.js // 构建配置
|--header.js // 头文件存放位置
|--addHeader.js // node脚本,用于往构建好的文件中添加头部描述

webpack.common.js 开发和构建通用webpack配置

const path = require('path')
const { CleanWebpackPlugin } = require('clean-webpack-plugin')
const VueLoaderPlugin = require('vue-loader/lib/plugin')

module.exports = {
  entry: {
    app: './src/main.js', // 入口文件位置
  },
  plugins: [
    new VueLoaderPlugin(),
    new CleanWebpackPlugin(), // 用于自动清除dist中的文件
  ],
  output: {
    filename: '[name].vue.js',
    path: path.resolve(__dirname, 'dist')
  },
  module: {
    rules: [
      // 按需添加rules
      {
        test: /\.(png|svg|jpg|gif)$/,
        use: [
          'file-loader'
        ]
      },
      // 处理Vue单文件组件,并使用scss
      {
        test: /\.vue$/,
        loader: 'vue-loader',
        options: {
          loaders: {
            'scss': [
              'style-loader',
              'css-loader',
              'sass-loader'
            ]
          }
        }
      }
    ]
  }
}

webpack.dev.js 开发环境配置

const merge = require('webpack-merge')
const common = require('./webpack.common.js')
const webpack = require('webpack')
const path = require('path')
const HtmlWebpackPlugin = require('html-webpack-plugin')

module.exports = merge(common, {
  mode: 'development',
  devtool: 'inline-source-map',
  devServer: {
    publicPath: '/',
    contentBase: path.join(__dirname, 'dist'),
    hot: true // hot reload
  },
  plugins: [
    new HtmlWebpackPlugin({
      title: 'test page'
    }),
    new webpack.HotModuleReplacementPlugin() // hot reload
  ]
})

webpack.prod.js 构建配置

const merge = require('webpack-merge')
const common = require('./webpack.common')

module.exports = merge(common, {
  mode: 'production',
  // 构建时不打包vue,而是通过在头文件中@require的方式引入
  externals: {
    vue: 'Vue'
  }
})

main.js 入口文件

import Vue from 'vue'
import App from './app.vue'

// 由于没有vuecli的index.html, 在这里创建一个dom元素来挂载vue
const root = document.createElement('div')
root.id = 'app'
document.body.appendChild(root)

new Vue({
  render: h => h(App)
}).$mount('#app')

headers

header.js中加入@require https://cdn.jsdelivr.net/npm/vue 来引入vue

addHeader.js中利用fs模块把header.js中的内容整合到dist中

项目地址

github.com/Jiny3213/vu…