NodeJS 开发应用

  • 使用的 Node 版本: V8.11.4
  • 开发工具: VSCode 1.27.1
  • 系统: Deepin 15.7 Desktop x64

项目结构

项目结构

  • Project

    • index.html
    • index.js
    • package.json
    • yarn.lock
    • rollup.config.js
    • src
      • Main.js
      • ...(js files)
      • subdirs
        • ...(js files)
    • build
      • main.js

yarn + rollup 构建应用程序

最近在学习使用打包工具 yarn 构建应用程序。

安装 yarn: npm i -g yarn。然后就可以在命令行中输入 yarn 命令:

$ yarn -v
1.9.4

使用 yarn init 初始化新项目,这会在当前目录下创建一些文件,其中 package.json 文件是配置文件。

在 package.json 中添加

{
... "scripts": {
"build": "rollup -c"
}
}

然后在终端中输入 yarn build,实际将会执行 rollup -c 命令,为了能够使用 rollup,我们需要先添加依赖:yarn add rollup

然后在当前目录下新建 rollup.config.js 文件,输入以下内容:

export default {
input: 'src/Main.js',
output: [
{
format: 'umd',
name: 'Main',
file: 'build/main.js',
indent: '\t'
},
{
format: 'es',
file: 'build/main.module.js',
indent: '\t'
}
]
};

接下来运行 yarn build,将会在当前目录下(若不存在则创建)创建一个 build 目录,里面有两个生成的文件 main.jsmain.module.js

在 Node 8.x 中监视文件变动情况

首先要引用 fs 模块: const fs = require('fs');fs 模块提供了 watch 方法,用于监视某个文件夹中的文件变动情况,使用的 NodeJS 版本为 8.x,原本该版本的 Node 已经提供了递归监视子文件夹的选项,但是由于 recursive 选项仅在 Windows 系统和 macOS 系统下生效,因此此处只能监视某个特定的文件夹。

以下是 nodejs 官网对 watch 函数的警告:

Caveats

The fs.watch API is not 100% consistent across platforms, and is unavailable in some situations.

The recursive option is only supported on macOS and Windows.

对于文件的监控实际上非常简单,fs.watch 方法会返回一个 fs.FSWatcher 对象,在该对象上注册 change 的回调函数即可。(也可以在调用 fs.watch 方法时将回调函数传递到第三个参数)

const fs =  require('fs');
const TO_WATCH = __dirname + '/src'; function onChange(eventType, filename) {
if( filename ) {
console.log( filename );
}
}; var watcher = fs.watch( TO_WATCH, { recursive: true } );
watcher.on( 'change', onChange );

接下来,使用 node 运行上述 JavaScript 代码,对 src 目录下的 Main.js 文件做一些改动,然后保存,在我的电脑的控制台上能够看到以下内容:

Main.js
Main.js

可以看到,代码正确运行了,并且能够监视出是哪个文件变动。(尽管还有些小问题,Main.js 输出了两次,稍后就会解决这个问题)

递归监视子文件夹

前面提到过,在 Linux 系统中,fs.watch(filename[, options][, listener]) 方法的 recursive 选项不起作用,然而在 src 目录下常常需要根据代码功能划分不同的子模块(子文件夹),如果不对 Linux 系统作一些额外的处理的话,那么前面给出的 JavaScript 代码将无法监视 src 下的子目录文件变动。

为了实现递归监视功能,需要用到 fs.readdir(path[, options], callback) 方法,在 node 10.x 中,该方法支持名为 withFileTypes: <boolean> 的选项,将该选项设为 true,在之后的回调函数中传递的 files 参数将不是一个字符串数组,而是一个 fs.Dirent[]。(fs.Dirent 对象自带有 isDirectory() 方法,自 10.10.0 版本后加入,使用起来是非常简单的。)

然而很遗憾,在 node 8.x 中,该方法的选项仅支持 encoding: <string>,回调函数中传递的 files 参数只是一个字符串数组,所以为了判断出 src 目录下的文件是否为文件夹,还需要 fs.stat(path, callback) 方法:

var watcher = [];
watcher[0] = fs.watch( TO_WATCH, { recursive: true } );
watcher[0].on( 'change', onChange ); // on linux watch recursive option is invalid
fs.readdir( TO_WATCH, { withFileTypes: true }, (err, files) => {
if( err ) {
throw err;
} for(let i = 0; i < files.length; i++ ) {
let file = files[i]
// file is just the name of certain file,
// we have to prepend "src/" or the absolute path
fs.stat( TO_WATCH + "/" + file, (err, stats) => {
if( err ) {
throw err;
} if( stats && stats.isDirectory() ) { let w = watcher.length;
watcher[w] = fs.watch( TO_WATCH + "/" + file );
watcher[w].on( 'change', onChange );
}
})
}
} );

一切都准备就绪,对 src 的子目录下的文件做出修改并保存,可以在控制台上看到修改的文件名(不过仍然会打印两次文件名,打印的次数根据系统环境等不同而不同,因为 fs.watch API 不是 100% 稳定的)。

为了防止修改一次文件而多次触发 onChange 回调函数,我们可以使用时间进行简单的过滤重复事件。

var last = Date.now();
function onChange(eventType, filename) {
let nd = Date.now();
if( nd - last > 100 && filename ) {
console.log( filename );
}
last = nd;
};

这里判断 onChange 方法执行的间隔时间,如果小于 100ms 就只需要执行一次命令。现在在尝试改动 src 目录下的文件,就只会打印一次文件名了。

文件变动时自动执行构建命令

执行命令需要用到 child_porcess 模块中的 exec 方法,使用起来比较简单,执行之前在终端中输入的命令 yarn build:

const exec = require('child_process').exec;

exec("yarn build", (err, stdout, stderr) => {
console.log( stdout );
});

这里只打印出标准输出,对于错误信息没有打印。

总结

以上不到 50 行的 JavaScript 代码就实现了递归监视目录及其子目录的功能,当目录中的文件变化时自动构建应用。由于 Node 10.x 中 watch 方法提供了递归监视的功能,可以对不同的 node 版本作不同的处理。但是这一功能并没有在本例的代码中实现。

完整代码在 github 仓库 上。

Reference

https://yarnpkg.com/zh-Hans/docs/getting-started

https://yarnpkg.com/zh-Hans/package/rollup

https://nodejs.org/docs/latest-v8.x/api/fs.html

NodeJS 开发应用的更多相关文章

  1. 十个最适合 Web 和 APP 开发的 NodeJS 框架

    在浏览器以外运行 JavaScript 对于 JavaScript 爱好者来说非常神奇,同时也肯定是 web 应用程序开发界最受欢迎的进步之一.全球各地的开发者张开双臂拥抱 NodeJS. 对于新手来 ...

  2. 10 个最适合 Web 和 APP 开发的 NodeJS 框架

    在浏览器以外运行 JavaScript 对于 JavaScript 爱好者来说非常神奇,同时也肯定是 web 应用程序开发界最受欢迎的进步之一.全球各地的开发者张开双臂拥抱 NodeJS. 对于新手来 ...

  3. nodejs初探(一)环境搭建,开发工具安装

    简介 JavaScript是一种运行在浏览器的脚本,它简单,轻巧,易于编辑,这种脚本通常用于浏览器的前端编程,但是一位开发者Ryan有一天发现这种前端式的脚本语言可以运行在服务器上的时候,一场席卷全球 ...

  4. NodeJS基础教程

    关于 本书致力于教会你如何用Node.js来开发应用,过程中会传授你所有所需的“高级”JavaScript知识.本书绝不是一本“Hello World”的教程. 状态 你正在阅读的已经是本书的最终版. ...

  5. Nodejs-第一篇(什么是NodeJS)

    NodeJS 介绍 Node.js 是什么? 1.Node.js 是一个开发平台,就像Java开发平台..Net开发平台.PHP开发平台.Apple开发平台一样: 什么是开发平台?它们有对应的编程语言 ...

  6. nodejs初探(一)nodejs开发环境搭建

    简介 JavaScript是一种运行在浏览器的脚本.Node.js是一个基于Chrome JavaScript运行时建立的平台, 用于方便地搭建响应速度快.易于扩展的网络应用.Node.js 使用事件 ...

  7. Nodejs课堂笔记-第四课 Dynamodb为何物

    本文由Vikings(http://www.cnblogs.com/vikings-blog/) 原创,转载请标明.谢谢! 我喜欢带着目标来学习新知识.因此学习nodejs过程中,不喜欢只看枯燥的语法 ...

  8. nodejs的调试debug

    目录 简介 开启nodejs的调试 调试的安全性 使用WebStorm进行nodejs调试 使用Chrome devTools进行调试 使用node-inspect来进行调试 其他的debug客户端 ...

  9. 如何做好 NodeJS 框架选型?

    作为一个有一定工作经验的工程师,工作中经常会遇到技术选型的问题.比如当我们在工作中需要使用到 NodeJS 时,第一个要解决的问题就是如何选择一个合适的框架. 不同的框架有不同的特点,如果我们仅仅从框 ...

随机推荐

  1. C#检测系统是否激活[转自StackOverFlow]

    using System; using System.Collections.Generic; using System.Text; using System.Runtime.InteropServi ...

  2. 读取word

    目标:将word中数据转存到数据库 实质:数据的读写 难点:word文件格式的处理(识别,读取),/ 提取word有效的相关字段 实现: 1.基础了解:word(文字处理应用程序/文档工具)软件   ...

  3. PL/0语言词法分析器

    前言:关于词法分析的基础知识的介绍可以看一下这篇博客,我再累述估计也不会有这篇讲的清楚QAQ. https://www.cnblogs.com/yanlingyin/archive/2012/04/1 ...

  4. DevExpress ASP.NET Dev控件客户端事件 ClientSideEvents

    原文地址:http://www.cnblogs.com/allenlf/p/4171189.html

  5. ORACLE 中dbms_stats的使用

    dbms_stats能良好地估计统计数据(尤其是针对较大的分区表),并能获得更好的统计结果,最终制定出速度更快的SQL执行计划. exec dbms_stats.gather_schema_stats ...

  6. Python学习过程(三)

    今天我们来学习怎么从网络上抓取我们想得到的信息,要从网页上得到我们的信息,首先是从网络上通过url获取页面 的文本,先从最简单的开始,比如获取百度首页的html. 对应代码如下: 获取网页html源码 ...

  7. 搜索【洛谷P2845】 [USACO15DEC]Switching on the Lights 开关灯

    P2845 [USACO15DEC]Switching on the Lights 开关灯 题目背景 来源:usaco-2015-dec Farm John 最近新建了一批巨大的牛棚.这些牛棚构成了一 ...

  8. swift -- 单例+ lazy懒加载 + 第三方库

    //工具类单例 static let goods : NHGoods = { let good = NHGoods() return good }() //懒加载 lazy var registerB ...

  9. zookeeper分布式锁简单实现(JavaApi)

    1.创建会话连接 package com.karat.cn.zookeeperAchieveLock.javaapilock; import org.apache.zookeeper.WatchedE ...

  10. inner join、left join、right join、full join

    A表 a1 b1 c1 01 数学 95 02 语文 90 03 英语 80  B表 a2 b2 01 张三 02 李四 04 王五 SQL语句:select A.*,B.* from A inner ...