Here is an example of how you might implement a login page with ExpressJS: First, set up your ExpressJS application and install the necessary dependencies: npm init npm install --save express body-parser express-session Ne... Read Creating Simple Login Page with ExpressJS
Initialize the Git repository
We can initialize a new Git repository in the project directory by adding the following command:
await $`git init`;
Generate package.json
Every Node.js project needs package.json
files. This is where we define metadata for our project, specify which packages our project depends on, and add useful scripts.
Before we generate the package.json
files for our project, we're going to create a couple of helper functions. The first is a readPackageJson
function that will read package.json
a file from the project directory:
async function readPackageJson(directory) {
const packageJsonFilepath = `${directory}/package.json`;
return await fs.readJSON(packageJsonFilepath);
}
Then we'll create a writePackageJson
function that we can use to package.json
write changes to the project's files:
async function writePackageJson(directory, contents) {
const packageJsonFilepath = `${directory}/package.json`;
await fs.writeJSON(packageJsonFilepath, contents, { spaces: 2 });
}
fs.readJSON
The sum fs.writeJSON
methods we used in the above functions are provided by fs-extra
the library.
After defining the package.json
helper functions, we can start thinking about package.json
the content of the file.
Node.js supports two module types:
module.exports
to export functions and objects and use them in another module to require()
load them.export
to export functions and objects and use them in another module to import
load them.The Node.js ecosystem is gradually adopting ES modules, which are common in client-side JavaScript. While things are in transition, we need to decide whether to use CJS modules or ESM modules by default for our Node.js projects. Let's create a promptForModuleSystem
function that asks which module type this new project should use:
async function promptForModuleSystem(moduleSystems) {
const moduleSystem = await question(
`Which Node.js module system do you want to use? (${moduleSystems.join(
" or "
)}) `,
{
choices: moduleSystems,
}
);
return moduleSystem;
}
The functions used by the above function are question
provided by zx.
Now we'll create a getNodeModuleSystem
function to call the promptForModuleSystem
function. It will check that the entered value is valid. If not, it will ask again:
async function getNodeModuleSystem() {
const moduleSystems = ["module", "commonjs"];
const selectedModuleSystem = await promptForModuleSystem(moduleSystems);
const isValidModuleSystem = moduleSystems.includes(selectedModuleSystem);
if (!isValidModuleSystem) {
console.error(
chalk.red(
`Error: Module system must be either '${moduleSystems.join(
"' or '"
)}'\n`
)
);
return await getNodeModuleSystem();
}
return selectedModuleSystem;
}
npm init
Now we can generate our project's package.json
files by running the command:
await $`npm init --yes`;
Then we'll use a readPackageJson
helper function to read the newly created package.json
file. We'll ask the project which module system it should use, and set it as packageJson
a property value in the object type
, and write it back to the project's package.json
file:
const packageJson = await readPackageJson(targetDirectory);
const selectedModuleSystem = await getNodeModuleSystem();
packageJson.type = selectedModuleSystem;
await writePackageJson(targetDirectory, packageJson);
Tip: To get sensible defaults in, when you --yes
run with flags, and make sure you set npm's config settings.npm init
package.json
init-*
Install required project dependencies
To make it easy to start project development after running our starter tool, we'll create a promptForPackages
function that asks which npm
packages to install:
async function promptForPackages() {
let packagesToInstall = await question(
"Which npm packages do you want to install for this project? "
);
packagesToInstall = packagesToInstall
.trim()
.split(" ")
.filter((pkg) => pkg);
return packagesToInstall;
}
To prevent typos when we typed the package name, we'll create a identifyInvalidNpmPackages
function. This function will accept an array of npm package names, then run npm view
the command to check if they exist:
async function identifyInvalidNpmPackages(packages) {
$.verbose = false;
let invalidPackages = [];
for (const pkg of packages) {
try {
await $`npm view ${pkg}`;
} catch (error) {
invalidPackages.push(pkg);
}
}
$.verbose = true;
return invalidPackages;
}
Let's create a getPackagesToInstall
function that uses the two functions we just created:
async function getPackagesToInstall() {
const packagesToInstall = await promptForPackages();
const invalidPackages = await identifyInvalidNpmPackages(packagesToInstall);
const allPackagesExist = invalidPackages.length === 0;
if (!allPackagesExist) {
console.error(
chalk.red(
`Error: The following packages do not exist on npm: ${invalidPackages.join(
", "
)}\n`
)
);
return await getPackagesToInstall();
}
return packagesToInstall;
}
If any package name is incorrect, the above function will display an error and then ask again which package to install.
Once we have a list of valid packages that need to be installed, we can npm install
install them using the command:
const packagesToInstall = await getPackagesToInstall();
const havePackagesToInstall = packagesToInstall.length > 0;
if (havePackagesToInstall) {
await $`npm install ${packagesToInstall}`;
}
Generate a configuration for the tool
Creating project configurations is the best thing we do automatically with the project launcher. First, let's add a command to generate a .gitignore
file so we don't accidentally commit files we don't want in our Git repository:
await $`npx gitignore node`;
The above command uses the gitignore package to pull the Node.js files from GitHub's gitignore template..gitignore
To generate our EditorConfig, Prettier, and ESLint configuration files, we'll use a command-line tool called Mrm.
mrm
Install the dependencies we need globally:
npm install --global mrm mrm-task-editorconfig mrm-task-prettier mrm-task-eslint
Then add mrm
the command line to generate the configuration file:
await $`npx mrm editorconfig`;
await $`npx mrm prettier`;
await $`npx mrm eslint`;
Mrm is responsible for generating configuration files and installing required npm packages. It also provides a large number of configuration options, allowing us to tweak the generated configuration files to suit our personal preferences.
Generate README
We can use our readPackageJson
helper function package.json
to read the project name from the project's file. We can then generate a README in basic Markdown format and write it to a README.md
file:
const { name: projectName } = await readPackageJson(targetDirectory);
const readmeContents = `# ${projectName}
this is the content tan.how of read me
...
`;
await fs.writeFile(`${targetDirectory}/README.md`, readmeContents);
In the above function, we are using fs-extra
the exposed fs.writeFile
promise variable.
Submit project skeleton
Finally, it's time to commit git
the project skeleton we created with:
await $`git add .`;
await $`git commit -m "Add project skeleton"`;
We'll then display a message confirming that our new project has started successfully:
console.log(
chalk.green(
`\n The project ${projectName} has been successfully bootstrapped!\n`
)
);
console.log(chalk.green(`Add a git remote and push your changes.`));
Start a new project
Now we can use the tools we created to start a new project:
mkdir new-project
./bootstrap-tool.mjs --directory new-project
And watch everything we do.
When mentioning control binding data in C#, most people first think of WPF. In fact, Winform also supports the binding of controls and data. Data binding in Winform can be divided into the following types according to the ...
Now that we've learned the basics of shell scripting with Google's zx, we're going to use it to build a tool. This tool will automate a usually time-consuming process: bootstrapping the configuration of a new Node.js ...