教你用NodeJs构建属于自己的前端脚手工具

目录
  • 一.前言
  • 二.技术栈
  • 三.特别说明
  • 四.构建项目
  • 五.安装依赖
  • 六.目录说明
  • 七.实战
    • (一).入口文件
    • (二).命令文件
    • (三).创建命令
    • (四).公共处理交互式命令
    • (五).选择项目框架交互式命令
    • (六).导出command命令
    • (七).导出inquirer交互式命令
    • (八).工具类代码
  • 八.本地测试
    • (一).完整输入
    • (二).不完整输入
  • 九.导入Vite + react18模板
  • 十.创建生成模板代码
    • 第一步:创建build文件夹
    • 第二步: config配置
    • 第三步:react生成模板
      • 1).getFiles 获取文件
      • 2).copyFile拷贝文件
      • 3).getCode获取代码
    • 第四步 分析createReact函数
    • 第五步 模板动态配置
    • 第五步 入口文件执行模板生成
  • 生成模板演示
    • (一).js版本
    • (二).ts版本
  • 总结

一.前言

在日常开发中,我们经常会用到各种脚手架工具,如常用的vue和react脚手架工具:vue-cli、Create React App。只需要执行内置命令和选择内置条件就可以生成对应的项目模板。极大的提高了我们开发开发效率,所以我们能不能根据自己的日常业务构建属于自己的一套脚手架工具呢,答案是可以的。接下来步入本文章的主题

二.技术栈

  • commander:^9.2.0 :完整的 node.js命令行解决方案
  • execa: ^6.1.0:执行shel命令
  • inquirer: ^8.2.4:交互式命令行用户界面,在命令工具中可提供交互
  • ejs: ^3.1.8:嵌入式JavaScript模板
  • chalk: ^5.0.1:设置终端字符串样式
  • mkdirp:^1.0.4:递归mkdir

三.特别说明

在开始之前,需要了解nodejs基础知识,常用shell执行命令,和javascript基础知识!!! 本文将从零到一完整讲解脚手架开发过程,以Vite + React18.0为模板案例,不会完整开发类似vue-cli 的所有功能!你可按照此文优化完善自己的脚手架代码。

四.构建项目

现在正式开始构建脚手架项目,可根据自己熟悉方式创建,直接创建项目文件夹

# 创建项目文件夹 名称为 my-cli 可自定义
mkdir my-cli
# 初始化 npm 根据自己的需求填写对应信息,也可以直接默认
npm init

五.安装依赖

yarn add commander execa inquirer chalk mkdirp
# or npm 安装
npm install commander execa inquirer chalk mkdirp

六.目录说明

完整目录,如下所示,可根据目录设计添加对应文件。

my-cli # 项目名称
└── bin # 主目录
    ├── commands # 命令文件
    │   ├── options # 命令所有选项
    │   │   ├── create.js # 创建命令
    │   │   ├── help.js # 帮助命令
    │   │   ├── help.js # 导出所有命令文件
    │   ├── index.js # 导出command命令方法
    ├── inquirers # 交互式命令文件
    │   ├── options # 交互式命令所有选项
    │   │   ├── common.js # 公共交互式命令
    │   │   ├── react.js # react相关命令
    │   │   ├── index.js # 导出所有交互式命令文件
    │   ├── index.js # 导出command命令方法
    ├── templates # 所有模板文件
    │   ├── react # react相关模板
    │   ├── vue # vue相关模板
    ├── utils # 工具类
    │   ├── index.js # 工具类处理函数
    ├── index.js # 入口文件

完整代码:my-cli

七.实战

在开始前,我们需要修改package.json文件,增加"bin": "./bin/index.js":发布到npm设置执行入口文件; "type": "module":表示允许执行export、import操作;"start": "node ./bin/index.js":做本地测试使用,表示执行脚手架入口文件

{
  + "bin": "./bin/index.js",
  + "type": "module",
  "scripts": {
    - "test": "echo \"Error: no test specified\" && exit 1",
    + "start": "node ./bin/index.js"
  }
}

(一).入口文件

首先从入口文件开始分析,需要的模块逐步完善。目录路径:bin/index.js

#! /usr/bin/env node
// 引入 fs模 块
import fs, { mkdirSync } from "fs";
// 引入 path 模块
import path from "path";

// 引入 commands 相关命令方法
import commands from "./commands/index.js";
// 获取用户输入、选择项
let config = await command();

需要注意的是#! /usr/bin/env node 表示执行环境为node,引入fs文件系统模块,创建文件项目会涉及到文件相关读取写能力;引入path读取文件路径。commands执行命令;通过let config = await command();获取用户输入、选择项;这一步涉及到commands所以接下来开始分析:bin/commands/index.js用户输入命令模块

(二).命令文件

目录路径:bin/commands/index.js

// 引入 commander 命令
import { program } from "commander";
import chalk from "chalk";
// 导入 create创建命令 help帮助命令
import { create, help } from "./options/index.js";

export default async (call) => {
  return new Promise((resolve, reject) => {
    program
      .name(chalk.blue("my-cli"))
      .usage("[global options] command");
    // 版本信息
    program.version("1.0.0");
    // 帮助信息
    program.option("-F, --framework", "surport vue,react");
    // 创建项目命令
    create(program, (item) => {
      resolve(item);
    });
    // 帮助信息
    help(program);
    // 解析指令
    program.parse(process.argv);
  });
};

我们需要关注的是create、help分别是创建命令、帮助命令

(三).创建命令

create创建命令 ,文件路径:bin/commands/options/create.js

/**
 * @description 创建项目指令
 * @author hu-snail 1217437592@qq.com
 */

 import inquirer from "inquirer";
 import { changeTemplate, changeVariant, inputProjectName } from "../../inquirers/options/index.js";
 import  {InvalidArgumentError} from "commander";
 import chalk from "chalk";
 import { hasTemplate, getSupportTs } from '../../utils/index.js'
 export default (program, call) => {
   program
     .command("create")
     .argument("<build-method>", "build tools", validatBuildMethod)
     .argument("[app-name]", "app name", validatAppName)
     .description("create a new project powered by my-cli")
     .option("-t, --template <value>", "create a new project by template", validatTemplate)
     .action(async (method, projectName, option) => {
       let item = {};
        // 判断用户是否输入 projectName
        if (!projectName) {
          item = await inquirer.prompt([inputProjectName(), changeTemplate(), changeVariant()]);
          // string转为boolean
          item.supportTs = item.supportTs === 'true' ? true : false
          return call && call({ method, ...item });
        }
       // 如果用户没有输入 模板参数,则提供项目类型选择 react/vue
       if (!option.template) {
         item = await getFramework(option);
				 item.supportTs = item.supportTs === 'true' ? true : false
       } else {
         item = option;
         item.supportTs = getSupportTs(item.template)
       }
       call && call({ method, projectName, ...item });
     });
 };

 /**
  * @description 校验构建方式
  * @param {String} appName 项目名称
  * @returns appName
  */
 function validatBuildMethod(val) {
   if (val === "vite") return val;
   else
     throw new InvalidArgumentError(
       chalk.red(
         `
         "<build-method>构建方式,只支持值为:${chalk.green(
           "vite"
         )}!请重新输入`
       )
     );
 }

 /**
  * @description 校验项目名称
  * @param {String} appName 项目名称
  * @returns appName
  */
 function validatAppName(appName) {
   var reg = /^[a-zA-Z][-_a-zA-Z0-9]/;
   if (!reg.test(appName)) {
     throw new InvalidArgumentError(
       chalk.red(`
       <app-name>项目名称必须以字母开头且长度大于2,请重新输入!`)
     );
   }
   return appName;
 }

/**
  * @description 校验模板
  * @param {String} template 模板名称
  * @returns template
  */
 function validatTemplate(template) {
   if (hasTemplate(template)) return template
   else {
    console.log(chalk.white(`error: option '-t, --template <value>' argument '${template}' is invalid`))
   }
 }

 async function getFramework() {
   let answer = await inquirer.prompt([changeTemplate(), changeVariant()]);
   return answer;
 }

思路分析:

上图所示,主要分两种情况,当用户完整输入和部分输入参数判。

关于program详细分析

.command("create"):表示创建一个名为create的命令;

.argument("<build-method>", "build tools", validatBuildMethod):其中argument:表示参数、<build-method>:表示构建方式,必填参数、build tools:表示参数描述、validatBuildMethod:表示自定义校验方法;

[app-name]:表示可选项,项目名称。<>:表示必填参数,[]:表示可选项

.description("create a new project powered by my-project-cli"):表示命令描述

.option("-t, --template <value>", "create a new project by template"):表示命令参数、 "-t, --template <value>":表示用户可输入-t--template:表示template参数、"create a new project by template":表示参数描述;

.action(async (method, projectName, option) => {}):表示命令行为事件,其中method, projectName:分别代表<build-method>构建方式、<app-name>项目名称,和顺序关联,可根据自己需求增删参数、option:表示参数选项、也就是"-t, --template <value>"可根据自己需求定义。

hasTemplategetSupportTs:分别表示是否存在模板,获取是否支持ts,在bin/utils/index.js可查看其用法

当用户没有完整输入项目框架时,我们会提供changeTemplatechangeVariantinputProjectName这个时候,就需要用到inquirer交互式命令提供选择项。

(四).公共处理交互式命令

文件路径:bin/inquirers/options/common.js

import chalk from "chalk";
export const changeVariant = () => {
    return {
      type: "list",
      name: "supportTs",
      choices: [
        {
          name: 'true',
        },
        {
          name: 'false',
        }
      ],
      message:
        "Support TS(default by javascript)",
    };
  };

  export const inputProjectName = () => {
    return {
      type: "input",
      name: "projectName",
      default: "vite-app-project",
      validate: function (appName) {
        var done = this.async();
        var reg = /^[a-zA-Z][-_a-zA-Z0-9]/;
        if (!reg.test(appName)) {
          done(chalk.red(`<app-name>项目名称必须以字母开头且长度大于2,请重新输入!`));
        }
        done(null, true);
      },
      message:
        "Project name",
    };
  };

参数解释,完整参数文档inpuirer文档

  • type:表示参数类型,提供input、number、confirm、list、rawlist、expand、checkbox、password、editor
  • name:表示参数属性
  • choices:选择项
  • message: 操作提示语
  • de'fa

其中changeVariant:选择是否支持ts;inputProjectName:输入项目名称

(五).选择项目框架交互式命令

文件路径:bin/inquirers/options/template.js

/**
 * @description 创建项目类型选择
 * @author hu-snail 1217437592@qq.com
 */

 export const changeTemplate = () => {
    return {
      type: "list",
      name: "template",
      choices: [
        {
          name: "react",
        },
        {
          name: "vue",
        },
      ],
      message: "Select a framework",
    };
  };

创建命令,到此结束,接下来分析help命令

文件路径:bin/commands/options/help.js

/**
 * @description 帮助信息
 * @author hu-snail 1217437592@qq.com
 */
 import chalk from "chalk";

 export default (program) => {
   program.addHelpText(
     "after",
     `
       Run ${chalk.green(
         "my-cli <command> --help"
       )} for detailed usage of given command.`
   );
 };

addHelpText:表示添加帮助文字,"after":表示在之后,可选项“before”,效果图如下

(六).导出command命令

文件目录:bin/commands/option/index.js

/**
 * @description 导出所有命令
 * @author hu-snail 1217437592@qq.com
 */
import create from "./create.js";
import help from "./help.js";
export { create, help };

(七).导出inquirer交互式命令

文件目录:bin/inquirers/option/index.js

/**
 * @description 导出用户输入选择项
 * @author hu-snail 1217437592@qq.com
 */
 import { changeTemplate } from "./template.js";
 import { changeVariant, inputProjectName } from './common.js'
 export { changeTemplate, changeVariant, inputProjectName };

(八).工具类代码

export function hasTemplate(template) {
    return ['vue', 'vue-ts', 'react', 'react-ts'].includes(template)
}

export function getSupportTs(template) {
  return ['vue-ts', 'react-ts'].includes(template)
}

这两个方法在react命令中使用到,补充!!!

八.本地测试

准备完以上代码后,我们开始本地测试,测试目的是检测是否能够正确的返回我们预设的结果,可根据自己的需求定义和完善脚手架。本文只是讲解demo流程!!!

(一).完整输入

完成输入测试包含正确输入、构建方式有误输入、项目名称不合规输入

js版本完成输入、默认为js版本

# react 版本
yarn start create vite app-test --template react
# or npm
npm run start create vite app-test--template react

效果图:

ts版本正确输入

# react-ts 版本
yarn start create vite app-test --template react-ts
# or npm
npm run start create vite app-test --template react-ts

效果图:

以上结果也就是我们入口文件:bin/index.jslet config = await command();获取的值

构建方法输入有误vite1:为错误输入  只支持vite方式构建,可根据自己的需求适配多种构建方式

yarn start create vite1 app-test
# or npm
npm run start create vite1 app-test

效果图:

项目名称不合规输入 1my-test-project:为不符合规范名称

yarn start create vite 1my-test-project --template react
# or npm
npm run start create vite 1my-test-project --template react

效果图:

(二).不完整输入

包含构建方式不输入、名称不输入、项目框架方式不输入

构建方式不输入会直接导致报错,重点是名称不输入、项目框架方式不输入,这时会给用户提供选择

项目名称不输入

yarn start create vite
# or npm
npm run start create vite 

效果图

项目名称不输入会提供默认值和输入给用户,同时完成项目框架选择、和是否支持ts选择。完整截图如下:

这个结果也就是我们入口文件:bin/index.jslet config = await command();获取的值

项目框架方式不输入

yarn start create vite app-test
# or npm
npm run start create vite app-test 

效果图:

不输入项目框架会提供选择,同时选择是否支持ts,完整截图如下:

到此结束测试,你可以根据这个思路完善自己的脚手架,接下来开始模板生成

九.导入Vite + react18模板

当我们能获取到用户输入选择的值后,就可根据用户输入的参数生成对应的项目模板,本文以vite+reat18为例

bin/templates目录下创建React模板文件,完整目录如下:

bin
├── templates # 所有模板文件
│   ├── react # react相关模板
│   │   ├── src # react主要文件
│   │   │   ├── App.css # App 样式文件
│   │   │   ├── App.jsx.ejs # App 模板文件
│   │   │   ├── index.css # 首页样式文件
│   │   │   ├── main.js.ejs # main 模板文件
│   │   │   ├── logo.svg # react logo文件
│   │   ├── .gitignore # git忽略配置文件
│   │   ├── index.html.ejs # react首页ejs模板
│   │   ├── package.json.ejs # package.json ejs模板
│   │   ├── tsconfig.json # ts 配置文件
│   │   ├── tsconfig.node.json # tsconfig node配置文件
│   │   ├── vite.config.js.ejs # vite.config ejs模板

具体代码,查看完整代码:github.com/hu-snail/my…

如果实现vite + vue3可参考此方法生成对应模板

模板技巧:不需要动态改变文件,直接使用原后缀名,例如:静态资源(图、视频、音等资源)、需要动态改变的文件,保留原来的后缀名,在其基础上添加.ejs:例如(package.jsonpackage.json.ejs)这样的好处是,知道原来的文件类型,方便更快的处理

十.创建生成模板代码

完成模板之后,开始重点环节,根据用户输入选择参数动态生成项目模板,跟着我的步骤完成生成模板语法

第一步:创建build文件夹

bin/创建build文件,用于存放生成模板文件和生成配置文件,目录如下:

bin
├── build # 生成模板文件
    ├── config.js # 模板配置文件
    ├── react.js # 生成react模板文件

第二步: config配置

因为脚手架内置了支持tsjs,所有存在差异化,具体配置如下:

/**
 * @description js需要忽略的文件
 */
export const jsignoreFile = [
    'tsconfig.json',
    'tsconfig.node.json'
]

其中模板中的tsconfig.jsontsconfig.node.jsonts才存在,所以在js需要忽略。可按照此方式区分文件之间的差异化。

第三步:react生成模板

准备完以上内容后,接下正式开始生成模板,文件路径:bin/build/react.js

/**
 * @description 生成react模板
 * @author hu-snail 1217437592@qq.com
 */

import fs from 'fs'
import mkdirp from "mkdirp";
import { getFiles, copyFile, getCode } from '../utils/index.js'
import { jsignoreFile } from './config.js'

代码分析:

代码中导入了getFilescopyFilegetCode三个方法,分别代表获取文件、拷贝文件、获取代码。首先从这三个方法开始分析,文件路径:bin/utils/index.js

1).getFiles 获取文件

import fs from "fs";
let files = []
let dirs = []
export function getFiles(template, dir) {
const templatePath = `./bin/templates/${template}/`
const rootFiles = fs.readdirSync(templatePath, 'utf-8')
rootFiles.map(item => {
  const stat = fs.lstatSync(templatePath + item)
  const isDir = stat.isDirectory()
  if (isDir) {
    const itemDir = `${template}/${item}/`.replace(/react\//g, '')
    dirs.push(itemDir)
    getFiles(`${template}/${item}`, itemDir)
  } else files.push((dir ? dir : '') + item)
})
return {files, dirs}
}

代码分析:

该函数提供两个参数,分别是templatedir,表示模板、目录,同时在方法前定义了两个变量filesdirs分别表示文件、目录,主要作用区分文件和目录,这样方便用于生成目录和创建文件。

  • templatePath:表示模板地址,根据传入template动态配置
  • rootFiles:表示所有模板文件,通过fs.readdirSync读取
  • stat:表示文件信息,通过fs.lstatSync获取
  • isDir: 表示是否目录,通过stat.isDirectory()判断,如果是则递归该目录下的所有文件
  • itemDir:表示层级目录,会把上一层接口也接入

2).copyFile拷贝文件

import fs from "fs";
import { fileURLToPath } from "url";
const __dirname = fileURLToPath(import.meta.url);
/**
  * @description 复制文件,比如图片/图标静态资源
  * @param {*} rootPath 根目录
  * @param {*} template 模板
  * @param {*} item 静态模板文件
  */
 export function copyFile(rootPath, template, item) {
   const fromFileName = path.resolve(
     __dirname,
     `../../templates/${template}/${item}`
   );
   const toFileName = `${rootPath}/${item}`;
   const rs = fs.createReadStream(fromFileName, {
     autoClose: true,
     encoding: "utf-8",
     highWaterMark: 64 * 1024 * 1024,
     flags: "r",
   });
   const ws = fs.createWriteStream(toFileName, {
     encoding: "utf-8",
     flags: "a",
     highWaterMark: 16 * 1024 * 1024,
     autoClose: true,
   });
   rs.on("data", (chunk) => {
     const wsFlag = ws.write(chunk, "utf-8");
     if (!wsFlag) {
       rs.pause();
     }
   });
   ws.on("drain", () => {
     // 继续读取
     rs.resume();
   });

   rs.on("end", () => {
     ws.end();
   });
 }

代码分析:

该函数提供三个参数rootPathtemplateitem,分别表示根目录,模板名称、静态模板路径。

  • fromFileName:表示读取文件地址
  • toFileName:表示拷贝至地址
  • rs:表示读取文件流,通过fs.createWriteStream创建
  • ws:表示写入文件流,通过fs.createWriteStream创建

3).getCode获取代码

import ejs from "ejs";
import fs from "fs";
/**
  * @description 解析ejs模板
  * @param {Object} config
  * @param {String} templateName
  * @param {String} templatePath
  * @returns code
  */
 export function getCode(config, templateName, templatePath) {
   const template = fs.readFileSync(
     path.resolve(__dirname, `../../templates/${templateName}/${templatePath}`)
   );
   const code = ejs.render(template.toString(), {
     ...config,
   });
   return code;
 }

代码分析:

该函数接受三个参数configtemplateNametemplatePath:分别表示配置信息、模板名称、模板地址

  • template:模板文件,通过fs.readFileSync读取
  • code: 模板代码,通过ejs.render提供生成
  • ...config: 用户输入选择的参数值,通过此参数动态生成对应模板

第四步 分析createReact函数

分析完工具函数代码之后,我们正式分析主函数createReact

/**
 * @description 生成react模板
 * @author hu-snail 1217437592@qq.com
 */

import fs from 'fs'
import mkdirp from "mkdirp";
import { getFiles, copyFile, getCode } from '../utils/index.js'
import { jsignoreFile } from './config.js'
export const createReact = (config, rootPath) => {
   // 创建项目
   mkdirp.sync(rootPath)
   const { template, supportTs } = config
   const reactTemplate = (template === 'react' || template === 'react-ts') ? 'react' : ''
   const { files, dirs } = getFiles(reactTemplate)
   // 创建文件夹
   dirs.map(item => {
    mkdirp.sync(`${rootPath}/${item}`)
   })

   files.map(item => {
    const isEjs = item.indexOf('.ejs') !== -1
    // 对模板文件进行操作
    if (isEjs) {
       const fileTyep = supportTs ? 'ts' : 'js'
       // 去掉ejs后缀
       const newItem = item.replace(/.ejs/g, '')
       // json后缀名不需要处理
       const isJson = newItem.indexOf('.json') !== -1
       // 替换后缀名
       const newFilePath = isJson ? newItem : newItem.replace(/js/g, fileTyep)
       // 写入相关模板文件
      fs.writeFileSync(
         `${rootPath}/${newFilePath}`,
         getCode(config, reactTemplate, item)
       )
    } else {
       // 如果不是ejs模板,直接复制文件
       if (supportTs) copyFile(rootPath, reactTemplate, item)
       else {
         // 判断是否存在js需要忽略的文件,即存在ts文件
         const hasTsFile = jsignoreFile.includes(item)
         if (!hasTsFile) copyFile(rootPath, reactTemplate, item)
       }
    }
   })
    return ''
}

代码分析:

该函数接受两个参数configrootPath:分别表示用户输入选择参数值配置、项目根目录。

  • mkdirp.sync(rootPath):通过mkdirp创建项目目录
  • reactTemplate:通过template传入的值reactreact-ts 统一react传入,因为模板目录只有react,可根据自己需求调整

其他项有代码注释,不一一赘述

第五步 模板动态配置

作为测试,我们对package.json.ejsindex.html.ejs进行动态配置,分别对应的目录bin/templates/react/package.json.ejsbin/templates/react/index.html.ejs

package.json.ejs:代码

{
  "name": "<%= projectName %>",
  "private": true,
  "version": "0.0.0",
  "scripts": {
    "dev": "vite",
    "build": "vite build",
    "preview": "vite preview"
  },
  "dependencies": {
    "react": "^18.0.0",
    "react-dom": "^18.0.0"
  },
  "devDependencies": {
    "@types/react": "^18.0.0",
    "@types/react-dom": "^18.0.0",
    "@vitejs/plugin-react": "^1.3.0",
    <%_ if (supportTs) { -%>
    "typescript": "^4.6.3",
    <%_ } -%>
    "vite": "^2.9.9"
  }
}

根据supportTs:判断是否需要"typescript",需要注意的<%_ -%>:语法会删除多余空行,如果使用<% %>:会导致留白,可以自行测试,"name": "<%= projectName %>":根据创建的项目名称生成

index.html.ejs:代码

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <link rel="icon" type="image/svg+xml" href="/src/favicon.svg" rel="external nofollow"  />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title><%= projectName %></title>
  </head>
  <body>
    <div id="root"></div>
    <script type="module" src="/src/main.jsx"></script>
  </body>
</html>

动态生成 <title><%= projectName %></title>

以上模板只是测试,可根据ejs模板语法,动态生成你需要的值

第五步 入口文件执行模板生成

接下来将在入口文件,执行我们的createReact函数

#! /usr/bin/env node
/**
 * @description 脚手架入口文件
 * @author hu-snail 1217437592@qq.com
 */
 import fs, { mkdirSync } from "fs";
 import path from "path";

 import command from "./commands/index.js";
 import { createReact } from './build/react.js'

 let config = await command();

 var currentPath = path.resolve("./");

 createReact(config, getRootPath())

 function getRootPath() {
    return `${currentPath}/${config.projectName}`;
 }

生成模板演示

现在可以看看具体效果

(一).js版本

yarn start create vite app-test -t react

效果图

生成目录

package.json文件

index.hml文件

(二).ts版本

yarn start create vite app-test -t react-ts

效果图

生成目录

package.json文件

index.hml文件相同

总结

到此这篇关于用NodeJs构建属于自己的前端脚手工具的文章就介绍到这了,更多相关NodeJs构建前端脚手工具内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • Node.js+Vue脚手架环境搭建的方法步骤

    Node.js的下载 node下载地址:https://nodejs.org/zh-cn/download/ 下载后安装即可.新版Node.js自带npm包管理器 # 查看node的版本 node -v # v12.16.1 # 查看npm版本 npm -v #6.13.4 第一个Node.js程序,新建helloworld.js文件,内容如下 console.log("Hello World") console.log("第一个Node.js程序!") 进入终端

  • 详解使用 Node.js 开发简单的脚手架工具

    前言 像我们熟悉的 vue-cli,react-native-cli 等脚手架,只需要输入简单的命令 vue init webpack project,即可快速帮我们生成一个初始项目.在实际工作中,我们可以定制一个属于自己的脚手架,来提高自己的工作效率. 为什么需要需要脚手架? 减少重复性的工作,不再需要复制其他项目再删除无关代码,或者从零创建一个项目和文件. 根据交互动态生成项目结构和配置文件等. 多人协作更为方便,不需要把文件传来传去. 思路 要开发脚手架,首先要理清思路,脚手架是如何工作的

  • 详解基于node.js的脚手架工具开发经历

    前言 我们团队的前端项目是基于一套内部的后台框架进行开发的,这套框架是基于vue和ElementUI进行了一些定制化包装,并加入了一些自己团队设计的模块,可以进一步简化后台页面的开发工作. 这套框架拆分为基础组件模块,用户权限模块,数据图表模块三个模块,后台业务层的开发至少要基于基础组件模块,可以根据具体需要加入用户权限模块或者数据图表模块.尽管vue提供了一些脚手架工具vue-cli,但由于我们的项目是基于多页面的配置进行开发和打包,与vue-cli生成的项目结构和配置有些不一样,所以创建项目

  • 详解nodejs解压版安装和配置(带有搭建前端项目脚手架)

    nodejs 安装 我先前用了nvm,觉得nvm挺厉害可以随时更换nodejs版本,但是研究了下,可能自己功力不够还是什么,并不好用,中间还出现了错误:所以最后还是卸载了: 本文图文并茂的一步一步的来,旨在好用简洁: 1]第一步:下载nodejs 中文官网: https://nodejs.org/zh-cn/download/ 如下图是最新的版本,不用怕这是最新的直接下载就可以了,选择windows版本,LTS是长期支持版本,箭头所示下载64位压缩版:个人觉得压缩版本就够了:(可能安装版的功能更

  • node脚手架搭建服务器实现token验证的方法

    内容 用脚手架快速搭建 node 项目 用 mysql 连接池实现与数据库的交互 用 jsonwebtoken 实现 token 身份验证 综合案例:用简介登录页面实现上述内容 1. 快速搭建 node 项目 我们都知道 express 框架可高效的开发 node 服务器,但对于底层的搭建还要靠自己手写.然而 express-generator 的出现就很好地解决了此问题,它可一键为我们生成项目基本骨架,可谓node 脚手架 1.1 生成项目 ①:首先全局安装 express : npm ins

  • node.js与vue cli脚手架的下载安装配置方法记录

    目录 一.node.js安装以及环境配置 1.下载vue.js 2.安装node.js 3.检查node程序是否安装成功 4.更改默认路径 5.添加环境变量 5.测试安装是否成功 二.安装vue-cli脚手架 1.检查node环境是否安装好 2.更改淘宝镜像下定制的cnpm(gzip 压缩支持) 命令行工具代替默认的npm 3.开始安装vue-cli 4.生成项目 5.打包上线 总结 一.node.js安装以及环境配置 1.下载vue.js 下载地址: https://nodejs.org/en

  • 搭建一个nodejs脚手架的方法步骤

    1 前言 1.1 像我们熟悉的 vue-cli,taro-cli 等脚手架,只需要输入简单的命令 taro init project ,即可快速帮我们生成一个初始项目.在日常开发中,有一个脚手架工具可以用来提高工作效率. 1.2 为什么需要脚手架 减少重复性的工作,从零创建一个项目和文件. 根据交互动态生成项目结构和配置文件等. 多人协作更为方便,不需要把文件传来传去. 1.3 怎样来搭建呢? 脚手架是怎么样进行构建的呢,我是借助了 taro-cli的思路. 1.4 本文的目标读者 1 想要学习

  • 开发Node CLI构建微信小程序脚手架的示例

    本文介绍了 Node CLI 构建微信小程序脚手架的示例,分享给大家,具体如下: 目的 由于目前公司的 TOC 产品只要是微信小程序,而且随着业务的扩展, 会有更多的需求,创建更多的小程序,为了让团队避免每次开发前花费大量时间做比如工程化的一些配置,以及保持每个项目的一致性, 所以决定做一个 Node CLI 来创建微信小程序脚手架 节省开发前期的大量时间,新项目可以很快开始业务开发 保证项目统一性,有利于团队间的协作及工程化 提升团队基建意识,从枯燥无味的业务开发中脱离出来,尝试新的东西,即使

  • 详解如何实现一个简单的Node.js脚手架

    原因 在工作中,需要开发一个脚手架,用于给相关用户提供相关的开发便利性. 适合人群 对前端.Node操作有一定的了解,同时向了解脚手架开发过程或者需要自己实现一个脚手架的开发者. 目标 开发一个简单的脚手架,能够提供给用户进行安装. 能够输出相关提示. 对用户文件进行读写操作. 在脚手架中使用Shell脚本. 步骤 开发脚手架 脚手架的开发最开始过程与普通的前端项目相同,需要一个入口文件command.js和配置文件package.json. 与其他配置文件不同的是,需要在package.jso

  • 教你用NodeJs构建属于自己的前端脚手工具

    目录 一.前言 二.技术栈 三.特别说明 四.构建项目 五.安装依赖 六.目录说明 七.实战 (一).入口文件 (二).命令文件 (三).创建命令 (四).公共处理交互式命令 (五).选择项目框架交互式命令 (六).导出command命令 (七).导出inquirer交互式命令 (八).工具类代码 八.本地测试 (一).完整输入 (二).不完整输入 九.导入Vite + react18模板 十.创建生成模板代码 第一步:创建build文件夹 第二步: config配置 第三步:react生成模板

  • 详解如何利用Nodejs构建多进程应用

    目录 前言 进程的创建和使用 多核利用率 创建子进程 进程间通信 IPC 总结 前言 JavaScript 主线程运行在单个进程的单个线程上.这样做的好处是: 程序状态是单一的,在没有多线程的情况下没有锁.线程同步问题, 操作系统在调度时因为较少上下文的切换,可以很好地提高CPU的使用率. 但是单进程单线程并非完美的结构,一旦线程中某段代码发生异常阻塞,会阻塞代码执行而浪费资源.同时,如今CPU基本均是多核的,服务器往往还有多个CPU. 因此 Nodejs 不可避免的面临两个问题:如何充分利用多

  • jenkins+docker+nginx+nodejs持续集成部署vue前端项目

    目录 前提: 思路: 步骤: 配置nodejs工具 git代码文件目录如下 Dockerfile的文件内容 nginx.conf主配置文件的内容 最近比较闲,尝试了一下docker部署业务测试环境的前端vue项目,作此记录 这里我的环境是Jenkins+docker+harbor+nginx部署,但是由于此项目以节点形式加入jenkins,构建和部署都在一台,所以没有用到harbor,但是生产环境可能部署和构建不在一台,会需要先推送到harbor,也有详细步骤. 前提: 1安装好了jenkins

  • 手把手教你把nodejs部署到linux上跑出hello world

    从事前端一年多了对于 linux 服务部署一直是一无所知, 知道前段时间萌发了个想法, 我怎么能像运维的同学一样把自己的代码放到一个 linux 的服务器上. 于是便开始了踩坑之旅, 这里顺便记录下. ps: 本文中需要下载的文件包括: VMware 下载 linux nodejs xshell 文件较大, 大家在上车动手之前可以先准备好下载文件在搞起来. 反正我是打了好几局 LOL 才下载完的. 首先安装 VMware 1. 下载 VMware 因为我们没有在 linux 上编程的必要(除非你

  • nodejs构建本地web测试服务器 如何解决访问静态资源问题

    直接打开html文件,是以file:///方式打开的,这种方式很多时候会遇到跨域的问题,因此我们一般会搭建一个简易的本地服务器,来运行测试页面. 一.构建静态服务器 1.使用express模块 建立个js文件,命名server,内容代码如下: var express = require('express'); var app = express(); var path = require('path'); //指定静态资源访问目录 app.use(express.static(require('

  • 5分钟教你用nodeJS手写一个mock数据服务器的方法

    对于前端开发者而言,javascript正扮演着越来越重要的地位,它不仅能为浏览器端赋能,在web服务器方面也有很大的价值(我们可以用nodeJS来写服务端代码,启动web服务器),因此本文所要描述的,便是javascript在服务端的应用.我将介绍如何使用nodeJS来搭建一个mock服务器,方便前端自定义mock数据请求,提高前端开发的主观能动性和对项目健壮性的探索. 我们将学到 koa基本使用 koa-router的基本用法 koa-logger的使用 glob支持文件遍历查寻 node几

  • 详解基于vue-cli3.0如何构建功能完善的前端架子

    上一篇文章写了vue和typescript的整合,发现很多小伙伴对vue-cli构建出来的项目很感兴趣,所以今天打算写写怎么在vue-cli3.0的架子上,在进一步完善,整合出具备基础功能的前端架子,主要包括以下几个功能点: webpack 打包扩展 css:sass支持.normalize.css rem布局 路由设计:懒加载.前置检查.合法性校验 api 设计 请求体设计-防重复提交 vuex状态管理 webpack 打包扩展 vue-cli3 最大的特点就是 零配置 ,脚手架把webpac

  • nodejs如何读取文件二进制 前端响应blob或base64显示图片

    目录 读取文件二进制 前端响应blob或base64显示图片 nodejs读取文件 createReadStream 读取文件二进制 前端响应blob或base64显示图片 express 框架 nodejs var express = require('express') var app = express(); var fs = require('fs') var http = require('http').createServer(app); app.get('/send',async

  • 使用nodejs中httpProxy代理时候出现404异常的解决方法

    在公司中使用nodejs构建代理服务器实现前后台分离,代码不能拿出来,然后出现httpProxy代理资源的时候老是出现404.明明被代理的接口是存在的.代码大概如下: var http = require('http'), httpProxy = require('http-proxy'); var proxy = httpProxy.createProxyServer({}); var server = http.createServer(function(req, res) { proxy.

  • 使用基于Node.js的构建工具Grunt来发布ASP.NET MVC项目

    Grunt 简介 Grunt是一款基于js和node.js的构建工具,由于这段时间node.js越来越火爆,grunt拥有丰富的开源社区支持,产生了很多插件.还有一些插件散落在node社区.构建是一个和宽泛的表述,传统理解就是编译.打包.复制,而今,随着技术越来越丰富,构建还包括对前端组件的预处理,比如sass.less预处理成css,css和js的压缩和合并.grunt的插件可以很好的支持这些新的构建概念,而且更为适合用开源技术堆砌的项目. 虽然Grunt更多的用于程序构建,但是本质上Grun

随机推荐