分享思源代码片段调试技巧

前言

思源的代码片段很强大,有了它你几乎可以无所不能。

但,你是不是也感受到了一点点烦恼?输入框不仅小,还每次调试都要先打开设置,再粘贴到输入框中。

如果你是开发者,频繁的打开和调试,你是不是开始感到有些心累?有没有一种办法,不需要频繁的打开也能进行调试预览呢?

答案是肯定的。

我在不断的打开与关闭的痛苦中摸索出了一些办法。

探索之路

先说 css

css 调试最简单的方式就是在右侧样式这里修改了

image.png

但这种修改方式还是有点麻烦,而且不小心刷新了页面,刚才改的样式全没了。

但你有没有注意到,如果点右上角的 + 号,然后在点击 inspector-stylesheet,你会发现会进入一个样式文件编辑界面。image.png

image.png

在这里同样能编辑样式,而且操作起来比在右侧方便多了。

但可惜的是,这里编写的 css 同样不能持久化,刷新同样会消失。

但你可以在每次重大操作后进行右键另存为。

image.png

但这同样很不方便,有没有能实时预览又能持久化的方法呢?

当然有,请参考下面的终极大招。

再说 js

js 最简单的方法就是控制台执行命令了,但这和 css 右侧调整样式一样非常不方便。

如果输入大量文本,还是碍手碍脚的,有没有办法...?有。

打开源代码,找到代码段选项卡,按照下图新建代码段即可。

image.png

然后,修改好后,在列表上右键运行即可

image.png

也可选中某一段右键在控制台运行

image.png

代码段中的代码可以保存和持久化。

但,怎么加载时运行呢?

代码段无法加载时运行。

请参考下面的终极大招。

终极大招

上面讨论了 css 和 js 的调试方法,都有不足,要么无法持久化,要么无法加载时运行。

要解决这两个问题,就得上我们的替换功能了。

image.png

这个功能的作用,就是用本地的文件替换远程的同名文件,这样就能通过编辑本地文件,就使得远程文件实时变化,就如同修改远程文件一样。

那么怎么做呢?

首先,在电脑随便新建个文件夹,任意路径都可,只要你找得到,比如叫 my-snippets,然后点选择放置替换的文件夹即可。

image.png

然后,你会发现,添加完了,什么都没有

image.png

莫慌,这里的的文件从哪里来呢?

有两种方式,一种来自思源中已加载的文件,另一种就是自己添加的文件。

先说第一种,就叫鸠占鹊巢法吧,为什么这么叫?因为这种方法会侵占别人的文件。

所谓的替换,就是指用本地的文件替换远程文件,这里的远程文件自然指思源自带的一些 css 或 js 文件了。

那么,我需要在本地新建文件吗?

不需要,因为我们只要打开左侧的网页选项卡,然后找到你想侵占的文件,然后右键选择替换内容即可。

image.png

image.png

看,有文件了

image.png

然后你只要在 theme.css 和 theme.js 文件中编辑即可,css 编辑时,样式会实时生效,非常方便。

js 如果需要加载执行的,需要刷新页面,如果想临时测试,可以选择执行的代码,使用右键在控制台评估所选文本即可。

那么,这里为什么选择 theme.js 呢?因为这个文件是空的呀,这不是正好方便我们拿来用于调试嘛。

至于 theme.css 里是有内容的,只需要在内容后面添加你的代码即可,注意不要误删除了原有内容,不过如果误删除了也没关系,找到 my-snippets 文件夹,删除后,重新来过即可。

当然,theme.css 里有内容,总是小心翼翼,你用着可能不爽,能不能...?能。

还记得刚才提到的 inspector-stylesheet 文件吗?这个文件也是可以支持替换内容功能的,同样的方法打开这个文件,然后右键选择替换内容即可。

image.png

然后,就可以在这个文件里愉快的编辑样式了,而且保存后能持久化到本地。

不过,这也有个缺点,就是这个文件默认不会自动加载,每次都要点一下样式那里的加号才出来,不过,添加替换内容只需要操作一次就行了,下次使用时,只需要点击下加号即可。

Nice,这看起来已经很完美了,那第二种添加自己的文件是啥?

这种方法由于是自己添加文件,不用思源原有的资源文件,我们就叫自定义文件法吧。

首先,在/data/public/snippets 文件夹中新建个文件夹,比如叫 demo,然后新建两个文件,比如叫 demo.js 和 demo.css。

然后,devtools 里找到刚才的网页选项卡,找到 app 文件

image.png

然后右键,替换内容,添加到替换文件夹即可。

然后打开,这个文件,在里面添加两行代码。

<script defer="defer" src="/public/snippets/demo/demo.js"></script>
<link href="/public/snippets/demo/demo.css" rel="stylesheet">

然后刷新页面,用同样的方法把 demo.js 和 demo.css 添加到替换文件里,然后就可以愉快的编辑了。

不过,这种方式还是麻烦了点,毕竟每次要手动添加两行代码,还是很不方便的,那么可以动态加载 js 和 css 吗?好主意,通过实验得知这样是可行的。

于是,我就写了下面的代码片段,就叫 loadSnippets 吧,然后把它放到思源 设置 》外观 》代码片段中即可。

代码如下:

(() => {
  
    // 配置要加载的项目,比如,load(["demo"]);
    load(["demo"]);

    // 设置load全局可访问,方便快捷开发
    window.loadSnippets = load;

    ////////////// 以下代码不涉及配置项,如果非必要勿改动 //////////////////////
   
    async function getAllFiles(path, includes = [], excludes = []) {
        let files = [];
        if(!includes) includes = [];
        if(!excludes) excludes = [];
        if(!Array.isArray(includes)) includes = [includes];
        if(!Array.isArray(excludes)) excludes = [excludes];
        const walkDir = async (currentPath) => {
            const response = await fetch('/api/file/readDir', {
                method: 'POST',
                body: JSON.stringify({ path: currentPath }),
            });
            const json = await response.json();
            const data = json.data;
            for (const entry of data) {
                const fullPath = `${currentPath}/${entry.name}`;
                if (
                    // 过滤仅包含文件
                    (includes.length && !includes.some(item=>fullPath.split("/").includes(item))) ||
                    // 过滤隐藏文件
                    currentPath.startsWith(".") ||
                    entry.name.startsWith(".") ||
                    // 过滤排除文件
                    excludes.includes(currentPath) || 
                    excludes.includes(entry.name)
                ) {
                    continue;
                }
                if (entry.isDir) {
                    await walkDir(fullPath);
                } else {
                    files.push(fullPath);
                }
            }
        };
        await walkDir(path);
        return files;
    }
  
    function loadStyle(url) {
      const link = document.createElement('link')
      link.type = 'text/css'
      link.rel = 'stylesheet'
      link.href = url
      document.head.appendChild(link);
    }
  
    function loadScript(url) {
        const script = document.createElement('script');
    	script.type = 'text/javascript';
    	script.src = url;
    	document.head.appendChild(script);
    }
  
    async function load(names = []) {
        const files = await getAllFiles("/data/public/snippets", names);
        files.forEach(file => {
            file = file.replace("/data", "");
            if(file.endsWith(".js")){
                loadScript(file);
            }
            if(file.endsWith(".css")){
                loadStyle(file);
            }
        });
    }
})();

这段代码的主要作用就是动态加载/data/public/snippets 下的 js 和 css 文件,还可以指定加载哪个项目。

开发完毕,注释加载即可,当然你也可以不注释,就当做代码片段来使用也是可以的 😄 。

不过,即使注释了,哪天你心血来潮或者想临时调试下某个项目,也可以直接在命令行加载,调用 window.loadSnippets("项目文件夹名") 即可。

那么,怎么让 devtools 中修改的文件和 public 中的文件相互保持同步呢?

这有点不好做,如果从 public 到 devtools 中,只能修改后重新加载文件,你可以写个监控脚本,当 public/snippets 中的文件改变时,实时加载,或者手动刷新也行,或者调用上面的 loadSnippets 命令重新加载。

如果从 devtools 到 public 呢?这个也可以写个监控脚本,当本地文件 my-snippets 文件发生改变时,实时同步到 public/snippets 中,但我通常调试无误后或重大修改后,在文件中右键,然后选择“另存为”保存到 public/snippets 中,感觉也挺方便的。

image.png

目前这些监控脚本有了吗?抱歉,并没有,不过你可以参考这位大佬的代码或利用 node 的 fs.watch 自己实现,关于监控我现在还没用到,感觉也没必要这么智能吧。

但要注意,如果你没有另存为,重启思源后,加载的 js 或 css 就不是最新版了,这是因为重启思源后端口变了,且在替换里修改的文件,只会保存在 my-snippets 目录,新端口不会用 my-snippets 里的旧文件替换,不过也没关系,打开 my-snippets,你修改过的文件都在这里,在 devtools 的替换列表里也能看到历史文件,然后复制过去就是了,记得开发完就保存一次。

如果你有兴趣,可以进一步完善这个方案。

注意:以上涉及的文件,如果找不到只需要刷新下页面即可,注意是刷新,不是重启思源,即在 devtools 控制台执行 location.reload()

另外,如果重启思源,上面添加的替换文件会失效,需要重新添加一遍,这是因为,思源每次重启后端口会变,对 devtools 来说,就相当于你换了一个网站,不同的网站下的内容当然不能共享了。

好在,我们开发时通常不需要频繁的重启思源,通常只需要刷新页面即可,这样的话,通常一个项目只需要添加一次即可,而且下一次添加时,只需要找到相应文件选择替换内容即可,比第一次方便方便多了。

这里顺便提一下,有人不清楚关闭和退出的区别。关闭不一定退出,比如如果你设置了关闭后进入托盘,则不会退出,只是隐藏在后台了,必须在思源主菜单中选择退出应用才最安全。

最佳实践

最后说说最佳实践。

我一般,如果临时调试样式时就用 inspector-stylesheet。

如果临时调试 js 通常用 theme.js,这个空文件,不用都对不起它 😄 。

如果开发具体项目就用自定义文件法 + 代码片段实现刷新加载,然后开发完另存为到 public/snippets 文件夹中即可。如果哪天你忘记另存为了,那么重启思源后,载的 js 或 css 就不是最新版了,这是因为重启思源后端口变了,且在替换里修改的文件,只会保存在 my-snippets 目录,新端口不会用 my-snippets 里的旧文件替换,不过,也没关系,打开 my-snippets,你修改过的文件都在这里,在 devtools 的替换列表里也能看到历史文件,然后复制过去就是了,记得开发完就保存一次。(重要事情多说一遍 😄 )。

而代码段(这里指 devtools 的代码段)我通常用放一些工具类的代码,方便快速执行或当做开发笔记使用。

不过,如果项目复杂,还推荐直接用官方的插件开发方法,而不是用代码片段了。

然后,在 devtools 里调试没问题后,再粘贴到思源代码片段中,这样就不用频繁打开和关闭思源代码片段了,是不是方便多了。

但要注意,放到思源代码片段中和利用 loadSnippets 动态加载两者别共存了,以防重复加载或产生冲突啥的。当然,如果你不想粘贴到思源代码片段中了,直接用 loadSnippets 来实现也是可以的。

最后我想说的是 devtools 就是一个方便的 IDE 啊,放一张图吧。

image.png

补充一点

刷新

刷新页面可以用快捷键 ctrl / cmd + r 必须当窗口焦点在 devtools 时按快捷键。
或者控制台执行 location.reload();

缩放

devtools 界面缩放可用快捷键
放大 ctrl+=
缩小 ctrl+-
还原 ctrl+0

这样在编写代码时看着就没那么累了。

笔记

开发笔记可以写到代码段里,不仅仅可以写代码哦

image.png

注意事项

在 devtools 中编辑文件时,有时候点击文字会被选中,不小心容易删除文字,要注意这一点。
不支持代码跳转,不过,可以用搜索代替。

如果非思源默认主题下,theme.js 可能不存在,不过,一般建议开发在一个新空间中进行,并使用默认主题,毕竟要保证正式空间的稳定性嘛,如果你必须用其他主题,那就用自定义文件法吧。


好了,啰嗦了这么多,希望对你有所帮助吧。

那么,你是怎么调试的呢?

请各位大佬们说说你的看法吧。

  • 思源笔记

    思源笔记是一款隐私优先的个人知识管理系统,支持完全离线使用,同时也支持端到端加密同步。

    融合块、大纲和双向链接,重构你的思维。

    23125 引用 • 93111 回帖 • 1 关注
  • 代码
    467 引用 • 586 回帖 • 9 关注
  • CSS

    CSS(Cascading Style Sheet)“层叠样式表”是用于控制网页样式并允许将样式信息与网页内容分离的一种标记性语言。

    196 引用 • 540 回帖 • 1 关注
  • JavaScript

    JavaScript 一种动态类型、弱类型、基于原型的直译式脚本语言,内置支持类型。它的解释器被称为 JavaScript 引擎,为浏览器的一部分,广泛用于客户端的脚本语言,最早是在 HTML 网页上使用,用来给 HTML 网页增加动态功能。

    728 引用 • 1275 回帖
3 操作
wilsons 在 2024-08-11 13:06:39 更新了该帖
wilsons 在 2024-08-11 10:33:06 更新了该帖
wilsons 在 2024-08-10 19:27:58 更新了该帖

相关帖子

欢迎来到这里!

我们正在构建一个小众社区,大家在这里相互信任,以平等 • 自由 • 奔放的价值观进行分享交流。最终,希望大家能够找到与自己志同道合的伙伴,共同成长。

注册 关于
请输入回帖内容 ...
  • wilsons

    👍 学习了。

  • 其他回帖
  • xqh042 1

    应该是开启客户端的第一个工作空间开启伺服时先使用 6806 端口吧,你是用手机端开启的伺服然后 pc 端访问调试吗?

    无法访问的话可以先确认一下电脑上访问(手机端伺服)网页用的是否是环回地址(本机地址,别名包括 127.0.0.1、[::1] 以及 localhost),不是的话可能要以 手机ip:6806 访问,并设置一下(手机端的)访问授权码。

    如果是 PC 端开启的伺服并且无法通过环回地址访问 6806 端口页面,可以检查下是否有其他应用占用了该端口:

    netstat -ano | findstr "6806"
    tasklist | findstr "末尾的PID"
    
    

    Clip20240810222949.png

    1 回复
  • 主要是跟插件就是类似的东西。

    还是得分发、版本维护、升级之类的各种操作,无外乎这个代码片段不调用思源 API 而已。。。用代码片段我都能让我之前旧时代插件系统跟现在的插件系统并存………

    Eagle 我看他们的插件不是依赖 github 的,是要提交给 eagle 官方的,我觉得可以吸收一下他们的做法。不过如果代码片段是直接分发的,那再弄套开源的 github 的插件方式,也怪怪的,两套都兼容,也不好描述

  • wilsons 1

    感谢提供的命令,但我试了下,6806 端口并未占用。

    而且我用 Python 启动了一个 HTTP 服务,端口用 6806 也能正常启动。

    说明不是端口占用问题。

    另外,我看论坛里有人提供的方法,通过 arp -a 查找手机端 ip 的方法,我这里不能用,不知道为什么,一直找不到手机端的 ip,只能找到电脑自己的 ip,但手机端的 ip 和电脑之间却可以相互访问。

    说明联通是没问题的,但就是找不到,不知道为什么。

    1 回复
  • 查看全部回帖