Preface With the release and increasing stability of Vite2, more and more projects are now trying to use it. When we use Vite, we usually use the following commands to create a project: // Using npm npm init @vitejs/app // Using yarn yarn create @vitejs/app // If you want to specify the project name and use a template for a specific framework, you can do it like this // npm npm init @vitejs/app my-vue-app --template vue //yarn yarn create @vitejs/app my-vue-app --template vue After running these commands, a project folder will be generated. For most people, it may be enough to create a project normally, but I am curious why a project folder will be generated when running these commands. Here we take yarn as an example to create a project. What does yarn create do? Many people may wonder why many projects are created using the yarn create command. In addition to Vite here, we create a React project in the same way: yarn global add create-react-app create-react-app my-app For more information about yarn create, see here Source code analysis After The folders starting with template are all project templates for various frameworks and corresponding typescript versions. We don’t need to worry too much about them. The logic of creating a project is all in the index.js file. Let’s take a look at what’s done here Project Dependencies The first is the introduction of dependencies const fs = require('fs') const path = require('path') const argv = require('minimist')(process.argv.slice(2)) const prompts = require('prompts') const { yellow, green, cyan, blue, magenta, lightRed, red } = require('kolorist') fs and path are built-in modules of Nodejs, while minimist, prompts, and kolorist are third-party dependency libraries respectively.
Template configuration Next, the configuration files of different framework templates are generated, and finally an array of template names is generated. // Here we only write the configuration of vue and react frameworks, the others are not much different, you can go to the source code if you are interested. const FRAMEWORKS = [ ...... { name: 'vue', color: green, variants: [ { name: 'vue', display: 'JavaScript', color: yellow }, { name: 'vue-ts', display: 'TypeScript', color: blue } ] }, { name: 'react', color: cyan, variants: [ { name: 'react', display: 'JavaScript', color: yellow }, { name: 'react-ts', display: 'TypeScript', color: blue } ] }, ...... ] // Output template name list const TEMPLATES = FRAMEWORKS.map( (f) => (f.variants && f.variants.map((v) => v.name)) || [f.name] ).reduce((a, b) => a.concat(b), []) Secondly, due to the particularity of the .gitignore file, a _gitignore file is created first under each framework project template, and then replaced with .gitignore when a project is created later. Therefore, an object will be pre-defined in the code to store the files that need to be renamed: const renameFiles = { _gitignore: '.gitignore' } Utility Functions Before we start talking about the core functions, let's take a look at the tool functions defined in the code. The most important are the three functions related to file operations. copyfunction copy(src, dest) { const stat = fs.statSync(src) if (stat.isDirectory()) { copyDir(src, dest) } else { fs.copyFileSync(src, dest) } } The copy function is used to copy the file or folder src to the specified folder dest. It will first get the status stat of src. If src is a folder, that is, stat.isDirectory() is true, it will call the copyDir function introduced below to copy the files in the src folder to the dest folder. On the contrary, if src is a file, the fs.copyFileSync function is directly called to copy the src file to the dest folder. copyDirfunction copyDir(srcDir, destDir) { fs.mkdirSync(destDir, { recursive: true }) for (const file of fs.readdirSync(srcDir)) { const srcFile = path.resolve(srcDir, file) const destFile = path.resolve(destDir, file) copy(srcFile, destFile) } } The copyDir function is used to copy files in a folder srcDir to the specified folder destDir. It will first call the fs.mkdirSync function to create the specified folder, then call fs.readdirSync to get the files from the srcDir folder and traverse and copy them one by one; finally, it calls the copy function to copy. Recursion is used here because there may be files or folders in the folder. emptyDirfunction emptyDir(dir) { if (!fs.existsSync(dir)) { return } for (const file of fs.readdirSync(dir)) { const abs = path.resolve(dir, file) if (fs.lstatSync(abs).isDirectory()) { emptyDir(abs) fs.rmdirSync(abs) } else { fs.unlinkSync(abs) } } } The emptyDir function is used to clear the code under the dir folder. It will first determine whether the dir folder exists. If it does, it will traverse the files in the folder and construct the file's path abs. When abs is a folder, it will recursively call the emptyDir function to delete the files in the folder, and then call fs.rmdirSync to delete the folder; when abs is a file, it will call the fs.unlinkSync function to delete the file. Core Functions Next is the init function that implements the core functionality. Command line interaction and creating folders The first step is to get the command line parameters let targetDir = argv._[0] let template = argv.template || argv.t const defaultProjectName = !targetDir ? 'vite-project' : targetDir argv._[0] represents the first parameter after @vitejs/app The specific code is as follows: // Some codes about command line interaction are not all put here. If you are interested, you can go to the source code let result = {} result = await prompts( [ { type: targetDir ? null : 'text', name: 'projectName', message: 'Project name:', initial: defaultProjectName, onState: (state) => (targetDir = state.value.trim() || defaultProjectName) }, ...... ] ) const { framework, overwrite, packageName, variant } = result const root = path.join(cwd, targetDir) if (overwrite) { emptyDir(root) } else if (!fs.existsSync(root)) { fs.mkdirSync(root) } template = variant || framework || template // Output project folder path console.log(`\nScaffolding project in ${root}...`) const templateDir = path.join(__dirname, `template-${template}`) After the selection is completed, the result of our selection will be returned Writing to a Fileconst write = (file, content) => { const targetPath = renameFiles[file] ? path.join(root, renameFiles[file]) : path.join(root, file) if (content) { fs.writeFileSync(targetPath, content) } else { copy(path.join(templateDir, file), targetPath) } } const files = fs.readdirSync(templateDir) for (const file of files.filter((f) => f !== 'package.json')) { write(file) } const pkg = require(path.join(templateDir, `package.json`)) pkg.name = packageName write('package.json', JSON.stringify(pkg, null, 2)) const pkgManager = /yarn/.test(process.env.npm_execpath) ? 'yarn' : 'npm' // Output some prompts to tell you that the project has been created, and tell you the command you need to run to start the project next console.log(`\nDone. Now run:\n`) if (root !== cwd) { console.log(` cd ${path.relative(cwd, root)}`) } console.log(` ${pkgManager === 'yarn' ? `yarn` : `npm install`}`) console.log(` ${pkgManager === 'yarn' ? `yarn dev` : `npm run dev`}`) console.log() The write function accepts two parameters file and content, and has two functions:
Then call fs.readdirSync to read the files in the template folder, traverse and copy them one by one to the project folder (the package.json file to be filtered because the name field in it needs to be modified); finally write to the package.json file. summary The implementation of Vite's create-app package has only about 320 lines of code, but it takes into account the compatibility of various scenarios; after learning it, it is not difficult to implement such a CLI tool by yourself. This is the end of this article about the implementation steps of Vite project creation. For more relevant Vite project creation content, please search 123WORDPRESS.COM's previous articles or continue to browse the following related articles. I hope everyone will support 123WORDPRESS.COM in the future! You may also be interested in:
|
<<: MySQL Workbench download and use tutorial detailed explanation
>>: MySQL5.7+ MySQL Workbench installation and configuration method graphic tutorial under MAC
You may often see some HTML with data attributes. ...
Table of contents 1. Build basic styles through E...
Table of contents View all storage engines InnoDB...
This article example shares the specific code of ...
Table of contents Preface: Implementation steps: ...
In the previous blog, Xiao Xiong updated the meth...
Install mysql5.7.18 on CentOS6.7 1. Unzip to the ...
You may sometimes need to create or delete symbol...
1. Concept 1. The difference between hot backup a...
Table of contents The first method: router-link (...
Preface Different script execution methods will r...
This article introduces the command statements fo...
Table of contents 1. Data Type 1. What is MySQL s...
Creating a Cursor First, create a data table in M...
This article example shares the specific code of ...