为什么是油猴, 而不是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中