当前位置: 首页 > news >正文

03_Node.js模块化开发

1 Node.js的基本使用

1.1 NPM

nodejs安装完成后,会跟随着自动安装另外一个工具npm

NPM的全称是Node Package Manager,是一个NodeJS包管理和分发工具,已经成为了非官方的发布Node模块(包)的标准。

2020年3月17日,Github宣布收购npm,GitHub现在已经保证npm将永远免费。可以在终端通过npm -v可以进行版本的查看,能够正确打印出版本,则表示安装成功。

npm版本可以更新,使用npm i -g npm既可进行更新。

设置国内源

因为npm下载的服务器在国外,有时候会导致下载速度很慢,所以一般我们安装完nodejs之后,会修改npm的源(把下载服务器改成国内的服务器)。

我们可以在终端输入下面的命令 npm config set registry [https://registry.npm.taobao.org](https://registry.npm.taobao.org)

回车后,不会有任何的反应。可以通过npm config get registry查看当前源是否是taobao源。

还原官方源

当我们需要用到官方源时,可以通过下面的命令进行还原npm config set registry [https://registry.npmjs.org/](https://registry.npmjs.org/)

1.2 Node.js的组成

JavaScript和Node.js的核心语法都是ECMAScript。

ECMAScript(核心语法):

  • JavaScript
    • 脚本语言,一般运行在客户端
  • Node.js
    • 运行在服务器端的JavaScript

JavaScript的组成:

  • ECMAScript
    • ECMAScript是JavaScript的核心语法。
  • DOM
    • DOM(文档对象模型)是HTML和XML的应用程序接口(API),用于控制文档的内容与结构。
  • BOM
    • BOM(浏览器对象模型)可以对浏览器窗口进行访问和操作。

JavaScript在客户端和服务端实现不同功能:

  • 客户端
    • JavaScript需要依赖浏览器提供的JavaScript引擎解析执行,浏览器还提供了对DOM的解析。
    • 客户端的JavaScript不仅应用了核心语法ECMAScript,而且能操作DOM和BOM。
    • 常见的应用场景如用户交互、动画特效、表单验证、发送Ajax请求等。
  • 服务器端
    • JavaScript不依赖浏览器,而是由特定的运行环境提供的JavaScript引擎解析执行,例如Node.js。
    • 服务器端的JavaScript应用了核心语法ECMAScript,但是不操作DOM和BOM,它常常用来做一些在客户端做不到的事情,例如操作数据库、操作文件等。
    • 另外,在客户端的Ajax操作只能发送请求,而接收请求和做出响应的操作就需要服务端的JavaScript来完成。

1.3 Node.js基础语法

通过node命令解析和执行一个js脚本文件的步骤如下:

  • 根据node命令指定的文件名称,读取js脚本文件。
  • 解析和执行JavaScript代码。
  • 将执行后的结果输出到命令行中。
// step 01
// 创建文件helloworld.js
console.log('hello world');// step 02
// 打开命令行工具,切换到helloworld.js文件所在的目录
// 并输入“node helloworld.js”命令。

1.4 Node.js全局对象global

全局对象window

在之前使用JavaScript的过程中,在浏览器中默认声明的变量、函数等都属于全局对象window,全局对象中的所有变量和函数在全局作用域内都是有效的。

例如,我们使用console.log()进行值的输出时,console.log()属于window对象的方法,又因为window是全局对象,所以在实际使用中可以省略掉window。

Node.js代码的运行环境存在window对象吗?

在Node.js代码的运行环境中没有DOM和BOM,因此也就不存在window对象。

那么使用的console.log()是来自于哪里呢?

在Node.js中,默认就是模块化的,默认声明的变量、函数都属于当前文件模块,都是私有的,只在当前模块作用域内可以使用。

Node.js中是否只有模块作用域?

答案是否定的,如果想在全局范围内为某个变量赋值,可以应用全局对象global。

Node.js中的global对象类似于浏览器中的window对象,用于定义全局命名空间,所有全局变量(除了global本身以外)都是global对象的属性,在实际使用中可以省略global。

// step 01
// 新建global.js文件
global.console.log('我是global对象中的console.log()方法');
global.setTimeout(() => {console.log('123');
}, 2000);// step 02
// 打开命令行工具,切换到global.js文件所在的目录,并输入“node global.js”命令。

2 Node.js系统模块

2.1 使用fs模块进行文件操作

原生的JavaScript语言无法操作文件,Node.js如何解决文件操作的问题?

Node.js为前端工程师提供了一组文件操作API,解决了前端开发文件操作的问题。

Node.js运行环境提供的APl都是以模块化的方式进行开发的,所以也把Node.js运行环境提供的API称为系统模块。

Node.js运行环境提供了很多系统模块,每一个系统模块中都具有相关性功能。

Node.js的文件操作API由fs(File System)模块提供,fs模块是Node.js的核心模块,不用额外安装就可以使用。

fs模块提供了fs.readFile()读取文件API、fs.writeFile()写入文件API,以及fs.mkdir()创建目录的API等。

模块加载

使用某个模块的API之前,首先需要加载这个模块,fs核心模块的模块标识为“fs”。

// require()方法的返回值
// fs模块的名字
const fs = require('fs');
文件读取

读取已有的文件,Node.js中文件读取的语法如下。

// 要读取文件的路径
// 文件编码(可省略)
// 回调函数
fs.readFile('文件路径/文件名称'[, '文件编码'], callback);

Node.js的文件读取

// step 01
// 在test目录下,新建a.txt作为被加载文件。
// Hello World// step 02
// 在test目录下新建file.js文件,读取文件。
// 1. 引用fs模块
const fs = require('fs');
// 2. 读取a.txt文件内容
fs.readFile('./a.txt', 'utf8', (err, data) => {console.log(err);	// nullconsole.log(data);	// Hello World
});// step 03
// 打开命令行工具,切换到file.js文件所在的目录,并输入“node file.js”命令。
文件写入

文件写入操作常用于网站运行的过程中,如果程序发生错误,将该错误写入到错误日志中,以便程序员对错误进行处理。

// 要写入文件的路径
// 要写入的内容
// 回调函数
fs.writeFile('文件路径/文件名称, 'data', callback);

Node.js的文件写入

// step 01
// 在test目录下,新建writeFile.js文件并编写如下代码向demo.txt文件中写入内容
// 1. 引用fs模块
const fs = require('fs');
// 2. 在demo.txt文件中写入内容
fs.writeFile('./demo.txt', '即将要写入的内容', err => {if (err != null) {console.log(err);return;}console.log('文件写入内容成功');
});// step 02
// 打开命令行工具,切换到writeFile.js文件所在的目录,并输入“node writeFile.js”命令。

2.2 使用path模块进行路径操作

在文件操作过程中,经常会遇到路径拼接的问题,那么如何把两个不完整的路径拼接成一个完整的路径?

针对这些路径字符串的操作问题,Node.js的Path模块提供了路径字符操作相关API。

函数说明
basename(p[,ext])获取文件名
dirname§获取文件目录
extname§获取文件扩展名
isAbsolute(path)判断是否是绝对路径
join([path1][,path2][,…])拼接路径字符串
normalize§将非标准路径转换为标准路径
sep获取操作系统的文件路径分隔符
加载模块

读取已有的文件,Node.js中文件读取的语法如下。

const path = require('path');

在Windows系统中使用path.join()方法拼接路径字符串

// 新建path.js文件
const path = require('path');
// 使用path.join()方法拼接public、uploads、avatar路径字符串
const finalPath = path.join('public', 'uploads','avatar');
// 使用finalPath变量来接收path.join()方法返回结果
console.log(finalPath);// 运行程序
// 打开命令行工具,切换到path.js文件所在的目录,并输入“node path.js”命令。
// public/uploads/avatar

不同操作系统的路径分隔符是不统一的,示例如下。

  • Windows系统中分隔符可以使用“/”或“\”;
  • Linux系统中分隔符为“/”。
相对路径和绝对路径

在Node.js中大多数情况下使用绝对路径,因为相对路径有时候相对的是命令行工具的当前工作目录。

例如文件读取操作API。Node.js中提供了与文件操作相关全局可用变量__dirname__dirname表示当前文件所在的目录,我们可以使用path.join()和__dirname进行路径拼接,从而获取当前文件所在的绝对路径。

Node.js中文件路径的获取

// 新建filename.js
const path = require('path');
console.log(__dirname);
console.log(path.join(__dirname, 'filename.js'));// 运行程序
// 打开命令行工具,切换到filename.js文件所在的目录,并输入“node filename.js”命令。

3 Node.js第三方模块

3.1 什么是第三方模块

第三方模块就是别人写好的、具有特定功能的、可以直接拿来使用的模块。

由于第三方模块通常都是由多个文件组成并且被放置在一个目录中,所以又称之为包。

第三方模块存在的两种方式:

  • 第1种是以js文件的形式存在,通常都是封装了一些特定的功能,并向外提供实现项目具体功能的API接口供开发者去调用,类似于jQuery。
  • 第2种是以命令行工具形式存在,提供了一些命令用于快速的安装和管理模块,辅助项目开发。

3.2 获取第三方模块

可以使用Node.js的第三方模块管理工具npm提供的命令去下载第三方模块。

npm在Node.js安装完成时就已经被集成,所以可以通过在命令行输入“npm -v”命令,按“Enter”键,来验证npm是否安装成功。

通过npm工具下载安装第三方模块

比如,需要安装的第三方包名称为formidable,就可以在C:\code\chapter02根目录下输入命令npm install formidable,并按“Enter”键等待安装成功即可(注意安装的过程必须联网)。

第三方模块安装成功

安装成功之后,Node.js会自动在项目的当前根目录下(C:\code\chapter02)创建一个node_modules目录,然后把第三方模块自动存放到该目录下。

在开发中使用第三方模块

在C:\code\chapter02目录下的js脚本中通过如下代码来加载formidable模块。

// 加载formidable模块
var formidable = require('formidable');// 卸载formidable模块
// npm uninstall formidable

在安装或者卸载第三方模块时,还有本地安装和全局安装的选项。

  • 本地安装指的是将模块下载到当前的项目当中,仅供当前项目使用。
  • 全局安装指的是将模块安装到一个公共的目录中,所有的项目都可以使用这个模块。
  • 在实际开发中,通常都会将库文件这种第三方模块进行本地安装,将命令行工具这种第三方模块进行全局安装。

4 Node.js常用开发工具

在Node.js中提供了常用的开发工具来帮助开发人员提高工作效率。

  • nodemon工具可以避免文件每次修改后的重新运行。
  • nrm工具可以快速切换npm的下载地址
  • gulp工具可以自动化处理项目日常任务。

4.1 nodemon工具

在Node.js中,每次修改文件都要在命令行工具中重新执行该文件。第三方模块nodemon解决了这个问题,它是一个用于辅助项目开发的命令行工具,每次保存文件时,代码都会自动运行。

通过npm工具下载安装nodemon工具

// -g全称为global表示全局安装
// npm install nodemon -g

4.2 nrm工具

nrm是npm中的第三方模块下载地址的管理工具,也是一个命令行工具,可以快速切换npm的下载地址。

因为npm中的第三方模块默认的下载地址在国外,在国内下载速度比较慢,有失败的可能。所以为了提高下载速度,在国内有一些公司建立了专门的服务器,用于存储Node.js第三方模块,例如阿里巴巴公司建立的registry.npm.taobao.org服务,它目前每隔10分钟就和npm官网服务做一次同步,可以替代官方的下载地址。

通过npm工具下载安装nrm工具

// -g全称为global表示全局安装
// npm install nrm -g

通过nrm ls命令查询当前可用的下载地址列表

通过nrm use命令切换下载地址列表

4.3 gulp工具

gulp是用JavaScript语言编写的运行在Node.js平台开发的前端构建工具。

gulp是一个JavaScript程序,并且它的指令使用的也是JavaScript语言,所以gulp通常是前端开发人员自动化处理日常任务的首选工具。

gulp工具作用

gulp可以处理日常工作流产生的任务:

  • 项目上线时对HTML、CSS、JavaScript文件合并、压缩。
  • 将ES6语法转换为ES5语法以便代码在较旧的浏览器中运行。

gulp允许开发者将机械化的操作编写成任务,在命令行输入相关的任务名称就能执行机械化操作,从而提高开发效率。

全局安装gulp-cli

gulp-cli是gulp的命令行工具,它需要全局安装,以便gulp能够在命令提示符中直接运行。gulp-cli是本地gulp的全局的入口,负责把所有参数转发到本地gulp,还有显示项目里安装的本地gulp的版本。

全局gulp用于启动各个项目中的本地gulp,换句话说,如果在全局安装了gulp-cli,那么就可以在不同的项目中使用不同的gulp版本。

通过npm工具下载安装gulp-cli

// -g全称为global表示全局安装
// @2.3.0表示全局gulp-cli的版本
// npm install gulp-cli@2.3.0 -g

在项目中安装gulp

本地gulp位于本地项目的node_modules目录下,包含了gulpfile所需的所有函数和API。

本地gulp作用:

  • 加载和运行gulpfile(gulpfile.js)中的构建指令。
  • 另一个是暴露API供gulpfile使用。
// 使用npm初始化项目
// 在项目目录下,初始化项目。
// npm init
// 命令完成之后会创建一个package.json新文件,该文件包存了项目的所有Node.js模块信息和版本。// 局部安装gulp
// 在项目目录下,执行如下命令。
// npm install gulp@4.0.2 --save-dev
// --save-dev表示将gulp作为devDependencice(开发依赖)保存到package.json文件中
// 命令执行成功后,会在项目根目录中生成一个node_modules目录和package-lock.json文件// 检测gulp-cli是否识别出了本地的gulp
// 再次在命令行工具中运行“gulp -v”命令检查gulp版本。

构建项目

  • 安装成功后,在项目根目录下建立gulpfile.js文件,注意这个文件名不能随意更改。
  • 重构项目的目录结构。
  • 在gulpfile.js文件中编写构建项目的任务。
// 引用gulp模块
const gulp = require('gulp');
// 使用gulp.task()方法建立任务
gulp.task('first', callback => {console.log('第一个gulp任务执行了')// 使用gulp.src()获取要处理的文件gulp.src('./src/css/base.css')// 将处理后的文件输出到dist目录 .pipe(gulp.dest('dist/css'));callback();
});
  • 在命令行工具中执行gulp任务。
// gulp first
// gulp命令后跟first任务名,表示gulp命令会自动去当前的项目根目录下查找gulpfile.js文件
// 然后在这个文件中再去查找first任务,找到后自动执行first任务的回调函数。
  • first任务的运行结果。

gulp API中的常用方法

方法说明
gulp.src()获取任务要处理的文件
gulp.dest()输出文件
gulp.task()建立gulp任务
gulp.watch()监控文件的变化

5 在项目中使用gulp

5.1 gulp中的常用插件

gulp第三方模块仅提供了一些常用的方法,使用这些方法只能实现一些基础的操作。

在gulp中如果我们想要处理文件的合并、压缩等操作,都需要通过哪些插件来实现?

gulp常用插件

插件说明
gulp-htmlmin压缩HTML文件
gulp-csso压缩优化CSS
gulp-babelJavaScrtipt 语法转化
gulp-lessLess语法转换
gulp-sassSass语法转换
gulp-uglify压缩混淆JavaScript文件
gulp-file-include公共文件包含
browsersync浏览器时间实时同步

5.2 压缩并抽取HTML中的公共代码

将HTML文件中的代码进行压缩,并抽取HTML文件中的公共代码

// stpe 01
// 在项目目录下,通过npm工具下载安装gulp-htmlmin插件
// 下载安装压缩HTML文件插件gulp-htmlmin
// npm install gulp-htmlmin// step 02
// 在gulpfile.js文件中引用gulp-htmlmin插件
// 引用gulp-htmlmin插件
const htmlmin = require('gulp-htmlmin');// step 03
// 在gulpfile.js文件中调用gulp-htmlmin插件,实现HTML文件中代码的压缩
gulp.task('htmlmin', (callback) => {gulp.src('./src/*.html')// 压缩html文件中的代码.pipe(htmlmin({ collapseWhitespace: true })).pipe(gulp.dest('dist'));callback();
});// step 04
// 查看dist目录结构
// 打开命令行工具,切换到项目目录,运行命令“gulp htmlmin”。
// gulp任务执行成功后,在dist目录可以看到两个压缩后的article.html文件和default.html文件
// 然后打开该文件,可以看到压缩后的代码。// step 05
// 下载gulp-file-include插件,抽取 HTML中的公共代码
// 在项目目录下,通过npm工具下载安装gulp-file-include插件。
// 下载gulp-file-include插件
// npm install gulp-file-include// step 06
// 在gulpfile.js文件中引用gulp-file-include插件
// 引用gulp-file-include插件
const fileinclude = require('gulp-file-include');// step 07
// 在gulpfile.js文件中调用gulp-file-include插件,抽取 HTML中的公共代码
gulp.task('htmlmin', (callback) => {gulp.src('./src/*.html')// 抽取HTML文件中的公共代码.pipe(fileinclude())// 压缩HTML文件中的代码.pipe(htmlmin({ collapseWhitespace: true })).pipe(gulp.dest('dist'));callback();
});// step 08
// src目录下新建 common 目录
// 然后在common目录下创建 header.html文件
// 并把头部的公共代码粘贴到header.html文件中。// step 09
// src目录下的default.html和article.html文件的头部代码删除掉,修改为如下代码。
@@include('./common/header.html')
// @@include()语法是由gulp-file-include插件提供的,小括号中是代码片段的路径以及文件的名字。// step 10
// 打开命令行工具,切换到目录,再次运行命令“gulp htmlmin”。
// gulp任务执行成功后,打开dist目录下的default.html文件和article.html文件
// 查看代码会发现这两个文件中都包含有 header 部分代码。

5.3 压缩并转换Less语法

将CSS文件使用的Less语法转换为CSS语法,并压缩CSS文件中的代码

// step 01
// 在test目录下,通过npm工具下载安装gulp-less插件
// 下载安装Less语法转换插件gulp-less
// npm install gulp-less// step 02
// 在gulpfile.js文件中引用gulp-less插件
// 引用gulp-less插件
const less = require('gulp-less');// step 03
// 在gulpfile.js文件中调用gulp-less插件,实现Less语法转换为CSS语法
gulp.task('cssmin', (callback) => {// 选择css目录下的所有.less文件gulp.src('./src/css/*.less')// 将Less语法转换为CSS语法.pipe(less())// 将处理的结果进行输出.pipe(gulp.dest('dist/css'))callback();
});// step 04
// 在 test\src\css 目录下,新建需要编译的a.less 文件。
/* .headers {
width: 100px;
.logo {
height: 200px;
background-color: red;
}
} */// step 05
// 打开命令行工具,切换到test目录,运行命令“gulp cssmin”。
// gulp任务执行成功后,打开项目下的 dist 目录
// 可以看到 css 目录下新建了一个同名的a.css文件。
// 需要对test\src\css目录下的全部文件进行压缩,然后输出。/* ---- css目录下有.less文件和.css文件 ---- */
/* ---- 那么如何同时获取这两种类型的文件并对其进行压缩呢? ---- */// step 06
// 在demo07目录下,通过npm工具下载安装gulp-csso插件。
// 下载gulp-csso插件
// npm install gulp-csso// step 07
// 在gulpfile.js文件中引用gulp-csso插件
// 引用gulp-csso插件
const csso = require('gulp-csso');// step 08
// 在gulpfile.js文件中调用gulp-csso插件,对CSS代码进行压缩
gulp.task('cssmin', (callback) => {// 选择css目录下的所有.less文件以及.css文件gulp.src(['./src/css/*.less', './src/css/*.css'])// 将Less语法转换为CSS语法.pipe(less())// 将CSS代码进行压缩.pipe(csso())// 将处理的结果进行输出.pipe(gulp.dest('dist/css'))callback();
});// step 09
// 打开命令行工具,切换到test目录,运行命令“gulp cssmin”。
// gulp任务执行成功后,打开项目下的 dist 目录,可以看到当前 css 目录结构。
// 打开css目录下的a.css文件,会发现代码已经被压缩了。

5.4 压缩并转换ES6语法

// step 01
// 在test目录下,通过npm工具下载安装gulp-babel插件。
// 下载安装gulp-babel插件,实现ES6语法的转换
// npm install gulp-babel @babel/core @babel/preset-env// step 02
// 在gulpfile.js文件中引用gulp-babel插件
// 引用gulp-babel插件
const babel = require('gulp-babel');// step 03
// 在gulpfile.js文件中调用gulp-babel插件,实现ES6语法的转换
gulp.task('jsmin', (callback) => {// 选择js目录下的所有JavaScript文件gulp.src('./src/js/*.js').pipe(babel({// 判断当前代码的运行环境,将代码转换为当前运行环境所支持的代码presets: ['@babel/env']})).pipe(gulp.dest('dist/js'));callback();
});// step 04
// 在 dtest\src\js目录下,新建需要编译的JavaScript文件(如base.js文件)。
/*
const x = 100;
let y = 200;
const fn = () => {
console.log(1234);
};
*/// step 05
// 打开命令行工具,切换到test目录,运行命令“gulp jsmin”。
// gulp任务执行成功后,打开项目下的 dist 目录
// 可以看到 js 目录下新建了一个同名的 base.js 文件。/* ---- 如何对test\src\js目录下的全部文件进行压缩,然后进行输出呢?? ---- */// step 06
// 下载gulp-uglify插件,对JavaScript文件进行压缩
// 在test目录下,通过npm工具下载安装gulp-uglify插件。
// 下载gulp-uglify插件
// npm install gulp-uglify// step 07
// 在gulpfile.js文件中引用gulp-uglify插件// step 08
// 在gulpfile.js文件中调用gulp-uglify插件,对JavaScript代码进行压缩
gulp.task('jsmin', (callback) => {// 选择js目录下的所有JavaScript文件gulp.src('./src/js/*.js').pipe(babel({// 判断当前代码的运行环境,将代码转换为当前运行环境所支持的代码presets: ['@babel/env']})).pipe(uglify()).pipe(gulp.dest('dist/js'));callback();
});// step 09
// 打开命令行工具,切换到test目录,运行命令“gulp jsmin”。
// gulp任务执行成功后,打开项目下的 dist 目录
// 可以看到当前js目录下的base.js文件会压缩了。

5.5 复制目录

对于test项目来说,还缺少src目录下的images目录和lib目录。接下来我们如何把src目录下的images目录和 lib目录,复制到dist目录下呢?

// step 01
// 在gulpfile.js文件中创建copy任务,进行目录复制操作。
gulp.task('copy', (callback) => {gulp.src('./src/images/*').pipe(gulp.dest('dist/images'));gulp.src('./src/lib/*').pipe(gulp.dest('dist/lib'));callback();
});// step 02
// 打开命令行工具,切换到test目录,运行命令“gulp copy”。
// gulp任务执行成功后,打开项目下的 dist 目录
// 可以看到js目录下新建了一个同名的images文件和lib文件。

5.6 执行全部构建任务

我们通过使用命令“gulp 任务名”去执行单个任务,那么如何实现执行一个任务,其他任务也一起执行呢?

// step 01
// 在gulpfile.js文件中创建default任务
// gulp.series()用于顺序执行任务
gulp.task('default', gulp.series('htmlmin', 'cssmin', 'jsmin', 'copy'));// step 02
// 打开命令行工具,切换到test目录,运行“gulp default”命令。

6 项目依赖管理

6.1 package.json文件

在进行模块化开发时,项目中需要记录复杂的模块依赖关系。随着时间的推移,项目中的某些模块可能会升级版本,模块提供的API也会发生变化,那么如何对模块进行有效管理呢?

将代码发给其他人或者上传到代码仓库时需要发送node_modules目录吗?

**不建议传输node_modules目录。**原因:node_modules目录中的文件多且零碎,当我们将整个项目进行复制时,传输速度会非常慢。

解决方案:npm工具提供了项目描述文件package.json,该文件中记录当前项目所依赖的第三方模块和对应的版本号,当其他人拿到这个项目的时候会根据package.json文件中所记录的依赖项下载第三方模块,这样项目在他人的计算机上也可以成功运行。

生成package.json文件

// -y表示全部使用默认值
npm init -y

查看package.json文件内容

{"name": "test",	// 表示项目的名称"version": "1.0.0",	// 表示项目的版本"description": "",	// 表示项目的描述"main": "index.js",	// 表示项目的主入口文件"scripts": {		// 对象中存储命令的别名"test": "echo \"Error: no test specified\" && exit 1"},"keywords": [],	// 表示关键字"author": "",	// 表示项目的作者"license": "ISC" 	// 表示项目遵循的协议,默认ISC
}

下载第三方模块

// 使用“npm install 模块名”命令去下载
npm install formidable mime// 会发现在原来的文件里新增了一个dependencies选项
"dependencies": {"formidable": "^1.2.2","mime": "^2.4.6"
}

如果删除项目目录结构中的node_modules目录,并将该项目传输给其他人,传输成功后,该如何运行这个复制的项目呢?

只需要在复制完成的项目中打开命令行工具,输入“npm install”命令,npm工具会自动到项目根目录下去找到package.json文件下的dependencies选项去下载第三方模块。

6.2 查看项目依赖

在项目的开发阶段和线上运营阶段,都需要依赖的第三方包,称为项目依赖。

例如,使用“npm install 包名”命令下载的formidable和mime第三方模块,它们会默认被添加到package.json文件的dependencies选项中。

除了项目依赖外,还有开发依赖。开发依赖使用“npm install 包名 --save-dev”命令安装,“--save-dev”参数将包添加到package.json文件的devDependencies选项中。

{"devDependencies": {"gulp": "^4.0.2"},
}

如何区分项目依赖和开发依赖

一般来说,devDependencies选项下的模块是在开发阶段需要用的,比如项目中使用的gulp模块等。这些模块在项目部署后是不需要的,所以可以使用–save-dev参数去安装。如果像jQuery和Express这些模块是项目运行中必备的,应该安装在dependencies选项中。

项目依赖和开发依赖进行区分的好处?

  • 可以在不同的运行环境中下载不同的依赖。例如在线下的开发环境我们可以使用“npm install”命令下载全部的依赖(包括项目依赖和开发依赖)。
  • 如果在项目上线后的运行环境(服务器环境)可以使用“npm install --production”命令下载dependencies选项(项目依赖),避免下载项目开发依赖。

在下载第三方模块时,npm会同时在demo08项目的根目录下产生一个package-lock.json文件,该文件中会详细记录模块与模块之间的依赖关系、版本信息,以及下载地址。

package-lock.json文件的两个作用

  • 一个作用是锁定包的版本,确保再次下载时不会因为包版本不同而产生问题。
  • 另一个作用是加快下载速度, 因为该文件中已经记录了项目所依赖第三方包的树状结构和包的下载地址,重新安装时只需下载即可,不需要做额外的工作。

7 Node.js模块加载机制

7.1 当模块拥有路径但没有后缀时

传入完整路径

当使用require()方法引入模块时,如果传入的是完整路径,那么程序就会根据模块路径查找模块,并直接引入模块。

require('./find.js');

模块后缀省略时

require('./find');

当模块后缀省略时,模块查找规则:

  • 首先在当前目录下查找find.js同名文件,如果找到就去执行这个同名的文件。
  • 如果当前目录没有找到find.js文件,那么就去查找当前目录下的find目录,如果找到这个目录,就在当前find目录下查找index.js文件,如果找到index.js文件就去执行这个文件。
  • 如果在find目录中没有找到index.js文件,就去当前find目录下的package.json文件中去查找main选项中的入口文件,如果找到入口文件就去执行它。
  • 如果main选项中没有指定入口文件,或者指定的入口文件不存在,程序就会报错。
// step 01
// 在项目目录下,创建test目录,在该目录下创建find.js文件作为被加载模块。
console.log('demo09目录下的find.js被执行了');// step 02
// 在test目录下,新建require.js文件。
require('./find');// step 03
// 打开命令行工具,切换到require.js文件所在的目录,并输入“node require.js”命令。// 如将demo09目录下的find.js重命名为任意一个名字(如nofind.js)
// 回到命令行重新执行“node require.js”命令。// step 04
// 在test目录下,新建find目录,并且在该目录下新建index.js文件
console.log('find目录下的index.js被执行了');// 当在test目录下没有找到find.js模块时,它就会去查到test目录下的find目录
// 然后在当前find目录下查找index.js文件,并去执行这个文件。// step 05
// 回到命令行工具,再次执行“node require.js”命令// 如果将find目录下的index.js文件,重命名为任意一个名字(如noindex.js)
// 回到命令行,切换到find目录下,执行“npm init -y”命令
// 在生成的package.json文件中将main选项值改为main.js。
// "main": "main.js",// step 06
// 在find目录下新建main.js文件。
console.log('find目录下的main.js被执行了');// 回到命令行工具,切换到test目录下,重新执行“node require.js”命令

7.2 当模块没有路径且没有后缀时

当使用require()方法引入模块时,如果只写了模块的名字,没有写模块的后缀,如下所示:

require('find');

当模块没有路径且没有后缀时,模块查找规则:

  • 首先,Node.js会假设它是系统模块,然后去系统模块中查找有没有find系统模块,如果有就去执行这个模块。
  • 如果没有找到find模块,就去node_modules目录中查找有没有同名的.js文件,如果找到了这个同名的.js文件就去执行它。
  • 如果在node_modules目录没有找到同名的.js文件,就在node_modules目录下查找有没有同名的find目录,如果找到这个目录,就在当前find目录下查找index.js文件,如果找到index.js文件就去执行这个文件。
  • 如果find目录中没有找到index.js文件,就去当前find目录下的package.json文件中去查找main选项中的入口文件,如果找到入口文件就去执行它。
  • 如果main选项中没有指定入口文件,或者指定的入口文件不存在,程序就会报错。
// STEP 01
// 在项目目录下,创建test目录,在该目录下创建require.js文件。
require('find');// STEP 02
// 在test目录下,创建node_modules目录,在该目录下新建find.js文件。
console.log('node_modules中的find.js被执行了');// STEP 03
// 打开命令行工具,切换到require.js文件所在的目录,并输入“node require.js”命令。// STEP 04
// 在node_modules目录下,新建find目录,并且在该文件下新建index.js文件,编写如下内容。
console.log('node_modules目录中的find目录中的index.js被执行了');// STEP 05
// 回到命令行工具,再次执行“node require.js”命令。// STEP 06
// 在find目录下新建main.js文件,编写如下内容。
console.log('find目录下的main.js被执行了');// STEP 07
// 回到命令行工具,切换到test目录下,重新执行“node require.js”命令

相关文章:

03_Node.js模块化开发

1 Node.js的基本使用 1.1 NPM nodejs安装完成后,会跟随着自动安装另外一个工具npm。 NPM的全称是Node Package Manager,是一个NodeJS包管理和分发工具,已经成为了非官方的发布Node模块(包)的标准。 2020年3月17日&…...

Nginx支持SNI证书,已经ssl_server_name的使用

整理了一些网上的资料,这里记录一下,供大家参考 什么是SNI? 传统的应用场景中,一台服务器对应一个IP地址,一个域名,使用一张包含了域名信息的证书。随着云计算技术的普及,在云中的虚拟机有了一…...

Hive【Hive(六)窗口函数】

窗口函数(window functions) 概述 定义 窗口函数能够为每行数据划分 一个窗口,然后对窗口范围内的数据进行计算,最后将计算结果返回给该行数据。 语法 窗口函数的语法主要包括 窗口 和 函数 两个部分。其中窗口用于定义计算范围…...

Met no ‘TRANSLATIONS’ entry in project

这里写自定义目录标题 问题描述:解决方法: 问题描述: 多工程项目,执行完update Translation生成了.ts文件,也用翻译工具翻译完了,执行release时,报错“Met no ‘TRANSLATIONS’ entry in proje…...

Leetcode901-股票价格跨度

一、前言 本题基于leetcode901股票价格趋势这道题,说一下通过java解决的一些方法。并且解释一下笔者写这道题之前的想法和一些自己遇到的错误。需要注意的是,该题最多调用 next 方法 10^4 次,一般出现该提示说明需要注意时间复杂度。 二、解决思路 ①…...

“传统文化宣传片+虚拟人动捕设备”前景如何?

在数字化时代的发展下,动捕设备的加入,让传播传统文化的虚拟人更具生动表现,拉近人们与传统文化的距离,通过虚拟人动作捕捉动画宣传片,引起更多人对传统文化的关注与传承。 *图片源于网络 深圳文博会创意短片《嗨ICIF…...

节假日moc服务数据:解决用户99%的IT问题

Hi~ 伙伴们,这个国庆假期过得怎么样? 节后第一个工作日如期而至, 忙碌是消除倦怠的最佳良药。 回顾8天假日moc工程师的一组服务数据, 处理事件184起,工单23条。 其中,较为典型案例如下: 1、福建某附属医院…...

WOL唤醒配置(以太网、PHY、MAC)

目录 wol 以太网 MAC PHY RMII 通信配置 总结 wol Wake-on-LAN简称WOL,WOL(网络唤醒) 是一种标准网络协议,它的功效在于让已经进入休眠状态或关机状态的计算机,透过局域网(多半为以太网&#xff…...

MySQL复制,约束条件,查询与安全控制

MySQL之复制 复制表 我有一个表 mysql> show tables; ------------------ | Tables_in_school | ------------------ | student | ------------------mysql> select * from student; -------------------------------------------- | id | name | sec |…...

Java ES 滚动查询

滚动查询(Scroll Query)是 Elasticsearch 提供的一种机制,用于处理大量数据的查询。它允许你在多个请求之间保持“游标”,以便在后续请求中获取更多的结果。 以下是滚动查询的基本工作原理: 1 初始查询: 客户端发送一…...

机器学习算法基础--KNN算法分类

文章目录 1.KNN算法原理介绍2.KNN分类决策原则3.KNN度量距离介绍3.1.闵可夫斯基距离3.2.曼哈顿距离3.3.欧式距离 4.KNN分类算法实现5.KNN分类算法效果6.参考文章与致谢 1.KNN算法原理介绍 KNN(K-Nearest Neighbor)工作原理: 在一个存在标签的…...

深入探究 C++ 编程中的资源泄漏问题

目录 1、GDI对象泄漏 1.1、何为GDI资源泄漏? 1.2、使用GDIView工具排查GDI对象泄漏 1.3、有时可能需要结合其他方法去排查 1.4、如何保证没有GDI对象泄漏? 2、进程句柄泄漏 2.1、何为进程句柄泄漏? 2.2、创建线程时的线程句柄泄漏 …...

BLE协议栈1-物理层PHY

从应届生开始做ble开发也差不读四个月的时间了,一直在在做上层的应用,对蓝牙协议栈没有过多的时间去了解,对整体的大方向概念一直是模糊的状态,在开发时也因此遇到了许多问题,趁有空去收集了一下资料来完成了本次专栏&…...

光伏储能直流系统MATLAB仿真(PV光伏阵列+Boost DCDC变换器+负载+双向DCDC变换器+锂离子电池系统)

💥💥💞💞欢迎来到本博客❤️❤️💥💥 🏆博主优势:🌞🌞🌞博客内容尽量做到思维缜密,逻辑清晰,为了方便读者。 ⛳️座右铭&a…...

C++三大特性——继承(上篇)

文章目录 目录 一、继承的概念及定义 1.1继承的概念 1.2 继承定义 1.2.1定义格式 1.2.2继承关系和访问限定符 1.2.3继承基类成员访问方式的变化 二、基类和派生类对象赋值转换 三、继承中的作用域 四、派生类的默认成员函数 一、继承的概念及定义 1.1继承的概念 继承(inherita…...

docker系列(9) - docker-compose

文章目录 9. compose编排9.1 介绍9.2 安装9.3 compose常用命令9.4 实战Springboot部署9.4.1 准备组件配置文件9.4.1.1 redis的配置文件9.4.1.2 MySQL的配置文件9.4.1.3 SpringBoot打包文件 9.4.2 准备docker-compose.yml9.4.3 启动服务9.4.4 测试验证 9.5 实战ElasticsearchKib…...

Vue中如何进行日历展示与操作

在Vue中创建交互式日历应用 在Web开发中,创建一个交互式的日历应用是一项常见的任务。Vue.js作为一个流行的JavaScript框架,提供了许多便捷的工具和组件来简化日历的开发。本文将介绍如何使用Vue来创建一个简单但功能强大的日历应用,包括展示…...

SpringBoot 返回图片、Excel、音视频等流数据几种处理方式

方式一:直接针对响应对象(response)实现 @RestController @Slf4j @Api(tags = SwaggerConfig.TAG_IMAGE) @RequestMapping(SwaggerConfig.TAG_IMAGE) public class ImageController {@GetMapping(value = "/getImage")@ApiOperation("获取图片-以ImageIO流形…...

【Vue面试题一】、说说你对 Vue 的理解

文章底部有个人公众号:热爱技术的小郑。主要分享开发知识、学习资料、毕业设计指导等。有兴趣的可以关注一下。为何分享? 踩过的坑没必要让别人在再踩,自己复盘也能加深记忆。利己利人、所谓双赢。 面试官:有使用过vue吗&#xff…...

vue3 axios

npm install axios import axios from axios // 创建axios实例 const request axios.create({baseURL: ,// 所有的请求地址前缀部分(没有后端请求不用写)timeout: 80000, // 请求超时时间(毫秒)withCredentials: true,// 异步请求携带cookie// headers: {// 设置后端需要的传…...

划片机:半导体生产的必备设备

划片机是半导体加工行业中的重要设备,主要用于将晶圆切割成晶片颗粒,为后道工序粘片做好准备。随着国内半导体生产能力的提高,划片机市场的需求也在逐渐增加。 在市场定位上,划片机可以应用于半导体芯片和其他微电子器件的制造过程…...

电路维修——双端队列BFS

达达是来自异世界的魔女,她在漫无目的地四处漂流的时候,遇到了善良的少女翰翰,从而被收留在地球上。 翰翰的家里有一辆飞行车。有一天飞行车的电路板突然出现了故障,导致无法启动。电路板的整体结构是一个 R 行 C 列的网格&#…...

乌班图22.04 kubeadm简单搭建k8s集群

1. 我遇到的问题 任何部署类问题实际上对于萌新来说都不算简单,因为没有经验,这里我简单将部署的步骤和想法给大家讲述一下 2. 简单安装步骤 准备 3台标准安装的乌班图server22.04(采用vm虚拟机安装,ip为192.168.50.3&#xff0…...

vue3富文本编辑器的二次封装开发-Tinymce

欢迎点击领取 -《前端面试题进阶指南》:前端登顶之巅-最全面的前端知识点梳理总结 *分享一个使用比较久的🪜 简介 1、安装:pnpm add tinymce / pnpm add tinymce/tinymce-vue > Vue3 tinymce tinymce/tinymce-vue 2、功能实现图片上传…...

typescript 类型声明文件

typescript 类型声明文件概述 在今天几乎所有的JavaScript应用都会引入许多第三方库来完成任务需求。这些第三方库不管是否是用TS编写的,最终都要编译成JS代码,才能发布给开发者使用。6我们知道是TS提供了类型,才有了代码提示和类型保护等机…...

Hadoop伪分布式环境搭建

什么是Hadoop伪分布式集群? Hadoop 伪分布式集群是一种在单个节点上模拟分布式环境的配置,用于学习、开发和测试 Hadoop 的功能和特性。它提供了一个简化的方式来体验和熟悉 Hadoop 的各个组件,而无需配置和管理一个真正的多节点集群。 在 Ha…...

javaee ssm框架项目添加分页控件

搭建ssm框架项目 参考上一篇博文 添加分页控件 引入依赖 <?xml version"1.0" encoding"UTF-8"?><project xmlns"http://maven.apache.org/POM/4.0.0" xmlns:xsi"http://www.w3.org/2001/XMLSchema-instance"xsi:schema…...

2023年中国非晶纳米晶竞争格局、产业链及行业产量分析[图]

非晶合金又称“液态金属、金属玻璃”&#xff0c;是一种新型软磁合金材料&#xff0c;主要包含铁、硅、硼等元素。其主要制品非晶合金薄带的制造工艺是采用急速冷却技术将合金熔液以每秒106℃的速度急速冷却&#xff0c;形成厚度约0.03mm的非晶合金薄带&#xff0c;物理状态表现…...

在业务开发中遇到的树形结构(部门、区域、职位),递归处理。

文章目录 概要对象结构示例完整示例小结 概要 本文主要记录在树形结构中会遇到的问题&#xff0c; 使用部门结构讲解&#xff0c;main方法进行演示。 1、获取部门树结构 2、根据部门id获取所有下级 3、根据部门id获取上级部门 4、根据部门id获取类似面包屑&#xff08;总公司…...

张量-算术操作函数

tf.add(x,y,name None)求和函数 示例代码如下: import tensorflow.compat.v1 as tf tf.disable_v2_behavior()x 1 y 2a tf.add(x,y)with tf.Session() as sess:print(sess.run(a)) tf.subtract(x,y,name None)减法函数 示例代码如下: import tensorflow.compat.v1 as …...

马云的网站怎么做的/合肥百度竞价推广代理公司

一、使用getters和setters 使用getters和setters获取对象数据比简单查找对象属性要好。因为&#xff1a; 1、当你想要做的不仅仅是获取对象属性&#xff0c;你不必查找和修改你代码中的每处访问。 2、使用set可以使验证变简单。 3、封装内部结构。 4、使用get和set&#xff0c;…...

深圳官方网站建设/优化大师网页版

$(.xxx).data(width,30%); 内容最少的一篇博客&#xff0c;嗯。...

wordpress注册邮件验证/新闻软文推广案例

异常 原因 是我浏览器使用的广告拦截插件阻止了请求的发送。我这里使用的广告拦截插件是ADGUARD。 解决 关闭该插件&#xff0c;但为了其他网页能拦截广告&#xff0c;应该过滤掉该页面。 能正常发送了 参考链接&#xff1a;接口请求跳坑&#xff1a; Status (blocked:other)…...

曲阜文化建设示范区网站/百度门店推广

Vue框架常见面试题 1、active-class是哪个组件的属性&#xff1f;嵌套路由怎么定义&#xff1f; 答&#xff1a;vue-router模块的router-link组件。 2、怎么定义vue-router的动态路由&#xff1f;怎么获取传过来的动态参数&#xff1f; 答&#xff1a;在router目录下的index…...

wordpress外网ip访问不了/2023年8月份新冠

Session 用于保存每个用户的专用信息. 每个客户端用户访问时&#xff0c;服务器都为 每个用户分配一个唯一的会话 ID&#xff08;Session ID) . 她的生存期是用户持续请求时 间再加上一段时间(一般是 20 分钟左右).Session 中的信息保存在 Web 服务器内 容中,保存的数据量可大可…...

建网站和建小程序多少钱/谷歌seo外链平台

该楼层疑似违规已被系统折叠 隐藏此楼查看此楼昂达v975w双系统(win10x86安卓5.1R1)安装教程微软也确实令人失望&#xff0c;在win10下&#xff0c;app还是这样子&#xff0c;所以楼主萌生了在不刷v975i的bios状况刷安卓&#xff0c;而是在win下的bios装上x86安卓玩耍安卓的海量…...