这篇文章转自掘金(https://juejin.cn/post/7138346293042085924 ),转载到这里一方面是因为掘金的排版不习惯,一方面当做收藏方便我随时回忆
前言 如何跟普通朋友介绍前端工程师是一个怎样的职位? 我会毫不犹豫的给他的浏览器装上 Tampermonkey,再装一个去广告插件 ,他们肯定会觉得你很牛逼,然后再问问他们,有些时候想复制某度文档,却复制不了,再给他们装一个 XX 文库的选中复制插件 ,瞬间成就感拉满,前端工程师就是干这个事的,笔者之前也写了几个油猴脚本,接下来我就分享下写脚本的经验,一起来看看吧。
什么是油猴脚本 Tampermonkey 是一款免费的浏览器扩展和最为流行的用户脚本管理器,它适用于 Chrome, Microsoft Edge, Safari, Opera Next, 和 Firefox。
「油猴脚本」是一段脚本代码,通过它可以让浏览器实现各种各样的扩展功能,和浏览器扩展的作用类似。 比如获去链接重定向、微博页面精简、去广告等,相当于给浏览器开了个挂,可以说是浏览器的辅助神器了!但浏览器扩展若要发布到 chrome 扩展市场,需要支付 5 美元,但「油猴脚本」可以随时随地发布,不需要支付任何费用费用。
新建脚本 在脚本管理控制台,右上角的+添加按钮,新建一个脚本,默认会包含以下代码:
最上面的注释不能删除,Tampermonkey 就通过注释代码来配置脚本字段的
CSDN 免登录复制 比如 CSDN 中代码块复制必须要登录后才可以复制, 那么我们就可以写一个脚本,输入以下代码
1 2 3 4 5 6 7 8 9 10 11 12 13 (function ( ) { 'use strict' ; $("pre,code" ).css ("user-select" ,"auto" ); })();
保存后,重新刷新浏览器,在右上角的扩展标志中会向上一个1, 说明有一个扩展作用于这个网页,脚本注入成功。
其实就是一行代码,CSDN 的默认代码块的样式是 user-select: none;,不能复制,改成 auto 后就可以复制了。
添加样式 首先需要在最上面的注释中开启权限 @grant GM_addStyle,然后就可以使用内置的 GM_addStyle 方法了。
1 2 3 4 GM_addStyle (`pre,code{user-select:auto !important}.signin{display: none !important;}` )
这样也可以解决 CSDN 代码块不能复制的问题,顺便将代码块后面的登录后复制按钮隐藏;
当然我们也可以使用 JS 自己实现
1 2 3 4 5 const heads = document .querySelector ('head' );const style = document .createElement ('style' );style.setAttribute ('type' , 'text/css' ); style.innerHTML = `pre,code{user-select:auto !important}.signin{display: none !important;}` ; heads.append (style);
网络请求
一般前端脚本都是修改前端网页内容,若复杂一点的脚本,可能会涉及到动态数据,比如我们在脚本中直接写fetch 请求,这时浏览器肯定会阻止请求,因为跨域了。
我们需要使用脚本的内置方法
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 GM_xmlhttpRequest ({ headers : { 'content-type' : 'application/json' , }, responseType : 'json' , url : 'https://api.juejin.cn/recommend_api/v1/article/recommend_cate_feed' , data : '{"id_type":2,"sort_type":200,"cate_id":"6809637767543259144","cursor":"0","limit":20}' , method : 'POST' , onreadystatechange : (res ) => { if (res.readyState === 4 ) { console .log (res.response ) } }, })
在最上面的注释中开启权限 @grant GM_xmlhttpRequest,然后就可以使用内置的 GM_xmlhttpRequest 方法了。
比如把接口换成有道翻译的 api。通过 document.getSelection().toString(); 获取网页中的选中文本,便可以实现一个划词翻译油猴插件了。
右键搜索 接下来我们将结合右键菜单和打开新窗口的内置函数,实现一个快捷搜索的功能, 同样内置函数需要在最上面的注释中加入权限,代码如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 GM_registerMenuCommand ("GitHub 搜索" , function ( ) { const str = document .getSelection ().toString (); if (str) { GM_openInTab (`https://github.com/search?q=${str} ` , { active : true }); } }); GM_registerMenuCommand ("NPM 搜索" , function ( ) { const str = document .getSelection ().toString (); if (str) { GM_openInTab (`https://www.npmjs.com/search?q=${str} ` , { active : true }); } });
这样就有了快捷菜单搜索的功能,只是操作挂着 3 级目录下,操作有些不方便。
以上简单介绍了脚本的开发以及一些简单实现,但这个脚本我们只能在自己电脑使用,若想让其他小伙伴也能够使用,我们需要将脚本发布到脚本脚本市场,供其他小伙伴下载。
脚本发布 一个非常流行的脚本共享网站便是 greasyfork.org ,有着非常丰富的脚本,并且支持多语言。
注册账号后,点击右上角的用户名,然后点击控制台中的发布你编写的脚本,贴入你写的脚本代码,便可以发布成功!将发布后的链接发送个小伙伴,就可以让他们安装你写的脚本了,你也可以在上面根据匹配域名搜索相关脚本,看大神们是如何来写脚本的。
前端工程化 现代前端开发已经离不开前端框架,若直接使用原生 JS 让我们写复杂的功能,难免会让我们崩溃,比如需要在 JS 中写 CSS,一不小心写错就会让整个脚本无法执行。所以我们可以使用 webpack 来构建一个工程化的项目。 并且使用 Typescript 和 eslint ,让我们的前端工程健全。
下面是 webpack.config.js
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 const webpack = require ("webpack" );const fs = require ("fs" );const path = require ("path" );const config = { entry : "./src/index.tsx" , output : { clean : true , iife : true , path : path.resolve (__dirname, "dist" ), filename : "bundle.js" , }, devServer : { static : { directory : path.join (__dirname, "public" ), }, compress : true , port : 9000 , }, optimization : { minimize : false , }, module : { rules : [ { test : /\.(js|jsx)$/ , use : "babel-loader" , exclude : /node_modules/ , }, { test : /\.css$/ , use : [ { loader : "style-loader" , options : {}, }, { loader : "css-loader" }, ], }, { test : /\.ts(x)?$/ , loader : "ts-loader" , exclude : /node_modules/ , }, ], }, plugins : [new BannerPlugin ()], resolve : { extensions : [".tsx" , ".ts" , ".js" ], }, }; module .exports = config;
使用 style-loader,在 webpack 打包后,会自动将 css 样式通过 style 标签插入到 head 中,这样就做到了css 和 js 分离。 这里有个问题,就是油猴脚本特有的代码前置注释 ==UserScript==,在webpack打包后会被删除,所以我们得自己实现一个插件,将这段注释加回来。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 const ConcatSource = require ("webpack-sources" ).ConcatSource ;class BannerPlugin { apply (compiler ) { let banner = "" ; const entryFile = compiler.options .entry .main .import [0 ]; const res = fs.readFileSync (entryFile, "utf-8" ); const matched = res.match ( /(\/\/\s==UserScript==)(?<content>(\n.+)+)(\n\/\/\s==\/UserScript==)/ ); if (matched && matched.groups .content ) { banner = "// ==UserScript==" + matched.groups .content + "\n// ==/UserScript==\n" ; } compiler.hooks .emit .tap ("BannerPlugin" , (compilation ) => { compilation.chunks .forEach ((chunk ) => { chunk.files .forEach ((fileName ) => { compilation.assets [fileName] = new ConcatSource ( banner, compilation.assets [fileName] ); }); }); }); } }
上述代码通过正则匹配 ==UserScript== 之间的代码,并且将匹配的内容合并到了最后的代码 chunk 中。
CICD 若我们每次打包后的 JS 都需要手动拷贝到 greasyfork.org 未免有些麻烦,得益于 greasyfork.org 有个自动发布的功能,我们可以配合 GitHub actions 来实现自动发布。
在项目文件夹下建立 .github/workflows/build.yml, 输入以下代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 name: GitHub Pages on: push: branches: - main pull_request: jobs: deploy: runs-on: ubuntu-20.04 permissions: contents: write concurrency: group: ${{ github.workflow }}-${{ github.ref }} steps: - uses: actions/checkout@v3 - name: Setup Node uses: actions/setup-node@v3 with: node-version: "14" - name: Get yarn cache id: yarn-cache run: echo "::set-output name=dir::$(yarn cache dir)" - name: Cache dependencies uses: actions/cache@v2 with: path: ${{ steps.yarn-cache.outputs.dir }} key: ${{ runner.os }}-yarn-${{ hashFiles('**/yarn.lock') }} restore-keys: | ${{ runner.os }}-yarn- - run: yarn install - run: yarn build - name: Deploy uses: peaceiris/actions-gh-pages@v3 if: ${{ github.ref == 'refs/heads/main' }} with: github_token: ${{ secrets.GITHUB_TOKEN }} publish_dir: ./dist
当我们把代码提交到 Github ,就会自动触发 workflow ,依次执行 yarn install 、yarn build 并且自动将 dist 目录下的代码自动部署到 GitHub pages。
接下来我们复制 pages 中的 raw 源文件地址
贴入复制的源文件地址
复制这里对应的 webhook 地址和秘钥
在 GitHub 项目地址中添加 webhook
这样只要我们一旦提交代码, greasyfork.org 中的脚本便会自动更新最新版本。
以上所有配置我整理在tampermonkey-starter 中, 若你也想创建一个自己的脚本,可以直接 fork 项目,修改相关配置即可。
小结 本文简单介绍了油猴脚本开发步骤以及实现,结合 webpack 让脚本实现工程化,并且配合 Github action,让脚本实现自动化构建和部署。
但是若想要实现一些有用的脚本,还需要具备更多的知识,比如JS逆向分析等,若你有好的想法,赶快行动起来吧!