本文主要梳理了 npm create
的功能,对比了 create-react-app
和 create-vite
的区别,并简单的实现了一个 create-myvite
的库学习创建逻辑。
从npm create 说起 npm create
是npm命令的一部分,用于通过npm运行特定的脚本或包来创建新的项目。它简化了创建项目的过程,特别是当你需要基于某个模板或特定工具来初始化项目时。
比如我们执行:
npm create
:
npm
是Node Package Manager的缩写,用于管理JavaScript包。
create
是一个关键字,表示你要运行一个创建项目的脚本。
xxx
:
xxx
表示你要使用的创建器包的名称。这可以是vite
,也可以是其他任何支持npm create
命令的创建器包。
当你运行npm create xxx
时,npm会执行以下步骤:
查找并下载创建器包 :
npm会从注册表中下载名为create-xxx
的包。例如,如果你运行npm create vite
,npm实际上会查找并使用create-vite
包。
执行创建器包的逻辑 :
下载并安装create-xxx
包后,npm会运行该包的创建脚本。这通常会涉及到询问用户一些问题(如项目名称、模板选择等),然后根据用户的输入来生成项目结构和文件。
create-vite 这个包具体做了什么 1 npm create vite@latest part1 -- --template react
这个命令用于通过Vite创建一个新的React项目。让我们逐步解释每个部分的含义:
vite@latest
确保使用的是最新发布的版本。
part1 : 这是新项目的名称。在这个例子中,项目将被创建在一个名为part1
的文件夹中。
– –template react : 这部分指定了模板。--template react
告诉Vite使用React模板来初始化项目。这意味着生成的项目将已经配置好React的相关依赖和文件结构。
询问用户输入 当你运行 npm create vite@latest
时,create-vite
包会启动一个命令行交互界面,询问你一些基本问题,比如项目名称、要使用的模板(如 React、Vue、Svelte 等)以及其他配置选项。
创建项目目录和文件
根据用户输入,create-vite
会在指定的目录下生成项目结构和文件。这些文件包括:
package.json
:定义项目的元数据和依赖。
index.html
:项目的入口 HTML 文件。
src
目录:包含源代码,通常会包含一个基本的 main.js
或 main.ts
文件,以及一个示例组件。
配置文件:如 vite.config.js
或 vite.config.ts
,用于配置 Vite。
安装依赖 如果你选择了特定的模板,create-vite
会自动添加相关的依赖到 package.json
中,并且会提供安装依赖的提示
提供运行指令 创建项目后,create-vite
会提示你下一步的操作,例如进入项目目录并运行开发服务器的命令(通常是 npm install
然后 npm run dev
)。
自己动手写一个脚手架 步骤 1:初始化项目 首先,创建一个新的 Node.js 项目:
1 2 3 4 mkdir create-myvitecd create-myvitenpm init -y
步骤 2:安装依赖 安装所需的依赖库,比如 inquirer
用于命令行交互,fs-extra
用于文件操作:
1 npm install inquirer fs-extra
步骤 3:编写脚本 index.mjs 文件
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 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 #!/usr/bin/env node import inquirer from 'inquirer' ;import fs from 'fs-extra' ;import path from 'path' ;import { fileURLToPath } from 'url' ;const __filename = fileURLToPath (import .meta .url );const __dirname = path.dirname (__filename);async function createProject ( ) { const answers = await inquirer.prompt ([ { type : 'input' , name : 'projectName' , message : 'Project name:' , default : 'my-vite-project' }, { type : 'list' , name : 'template' , message : 'Select a template:' , choices : ['vanilla' , 'react' , 'vue' ] } ]); const { projectName, template } = answers; const projectPath = path.join (process.cwd (), projectName); if (fs.existsSync (projectPath)) { console .error (`Error: Directory ${projectName} already exists.` ); process.exit (1 ); } fs.mkdirSync (projectPath); fs.writeFileSync (path.join (projectPath, 'index.html' ), `<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" /> <title>Vite App</title> </head> <body> <div id="app"></div> <script type="module" src="/src/main.js"></script> </body> </html>` ); let dependencies = {}; let devDependencies = { vite : "^3.0.0" }; const srcDir = path.join (projectPath, 'src' ); fs.mkdirSync (srcDir); if (template === 'react' ) { dependencies.react = '^17.0.0' ; dependencies['react-dom' ] = '^17.0.0' ; fs.writeFileSync (path.join (srcDir, 'main.jsx' ), `import React from 'react'; import ReactDOM from 'react-dom'; import App from './App'; ReactDOM.createRoot(document.getElementById('app')).render(<App />);` ); fs.writeFileSync (path.join (srcDir, 'App.jsx' ), `import React from 'react'; function App() { return <h1>Hello, Vite + React!</h1>; } export default App;` ); } else if (template === 'vue' ) { dependencies.vue = '^3.0.0' ; devDependencies['@vitejs/plugin-vue' ] = '^2.0.0' ; fs.writeFileSync (path.join (srcDir, 'main.js' ), `import { createApp } from 'vue'; import App from './App.vue'; createApp(App).mount('#app');` ); fs.writeFileSync (path.join (srcDir, 'App.vue' ), `<template> <h1>Hello, Vite + Vue!</h1> </template> <script> export default { name: 'App' }; </script>` ); fs.writeFileSync (path.join (projectPath, 'vite.config.js' ), `import { defineConfig } from 'vite'; import vue from '@vitejs/plugin-vue'; export default defineConfig({ plugins: [vue()] }); ` ); } else { fs.writeFileSync (path.join (srcDir, 'main.js' ), `document.getElementById('app').innerHTML = '<h1>Hello, Vite!</h1>';` ); } fs.writeFileSync ( path.join (projectPath, "package.json" ), JSON .stringify ({ name : projectName, version : "0.0.1" , scripts : { dev : "vite" , build : "vite build" , serve : "vite preview" }, dependencies, devDependencies }, null , 2 ) ); console .log (`Project ${projectName} created successfully.` ); console .log (`Navigate to the project directory and run 'npm install' to install dependencies.` ); } createProject ();
package.json文件
1 2 3 4 5 6 7 8 9 10 11 12 13 14 { "name" : "create-myvite" , "version" : "1.0.0" , "type" : "module" , "main" : "index.mjs" , "bin" : { "create-myvite" : "./index.mjs" } , "dependencies" : { "inquirer" : "^8.1.2" , "fs-extra" : "^10.0.0" } }
步骤 4:添加执行权限和链接 使 index.mjs
文件可执行,并创建全局链接:
1 2 3 chmod +x index.mjsnpm link
运行示例 运行以下命令来创建一个新项目:
create-vite
和 CRA(create-react-app
)比较相似之处
快速搭建应用程序: 两者都旨在简化新项目的搭建过程。通过运行一个命令,你可以快速创建一个基本的项目结构,并且可以立即开始编写代码。
现代化的工具链: 两者都使用了现代化的工具链,包括 Babel、Webpack、ESLint 等,以确保你可以使用最新的 JavaScript 特性,并且具备良好的开发体验。
默认配置: 默认情况下,它们提供了一个预配置的开发环境,包括热重载、代码分割、生产构建等功能。
区别
构建工具: 最明显的区别是它们使用的构建工具不同。create-react-app
使用的是 Webpack,而 create-vite
使用的是 Vite。Vite 是一个由 Vue.js 核心团队开发的新型前端构建工具,它利用了现代浏览器对 ES 模块的原生支持,能够实现非常快速的开发构建速度。
模块热更新(HMR): create-vite
基于 Vite,利用了浏览器原生支持的 ES 模块特性,因此具有更快的热更新速度。而 create-react-app
使用的 HMR 则是基于 Webpack 的实现,速度相对较慢。
生态系统: 由于 create-react-app
是由 Facebook 团队维护的,因此它更倾向于与 React 生态系统无缝集成。相比之下,create-vite
在刚推出时可能会受到生态系统限制,但由于 Vite 本身已经得到了 Vue.js 社区的广泛支持,因此其生态系统也在不断壮大。
生产构建方式: create-react-app
使用 Webpack 来构建生产环境的代码,而 create-vite
则使用 Rollup 来构建生产代码。Rollup 是一个专注于构建 JavaScript 库的工具,通常被认为比 Webpack 更适合用于构建库和框架。
总的来说,create-vite
相对于 create-react-app
更加轻量、快速,尤其适合于构建 Vue.js 项目或者需要更快速开发体验的应用程序。但在选择工具时,还应考虑到项目的具体需求和团队的熟悉程度。