Make a TIME Management Tool for the CLI (13)

This is the 14th day of my participation in the August More Text Challenge. For details, see “August More Text Challenge”.

preface

In the previous article, I added a timec Page directive to start a Web service

This issue will continue to refine the effects of this directive

Preview of effect

The function development

The Web side

I plan to use Vue3 to develop the page

Installation project dependencies

yarn add vue@next @vue/compiler-sfc @vitejs/plugin-vue
Copy the code

Quickly create a Vite+Vue3 template project

npm init vite@latest my-vue-app --template vue
Copy the code

The completed directory structure is as follows

My - vue - app ├ ─ ─ index. The HTML ├ ─ ─ package. The json ├ ─ ─ public | └ ─ ─ the favicon. Ico ├ ─ ─ the SRC | ├ ─ ─ app. Vue | ├ ─ ─ assets | ├ ─ ─ Components | └ ─ ─ main. Js └ ─ ─ vite. Config. JsCopy the code

We will vite. Config. Js, main js, components, App. Vue, index. The HTML copy the contents of these five parts to the SRC/page directory of our project

The directory after the copy is complete is as follows

├ ─ ─ App. Vue ├ ─ ─ assets | └ ─ ─ logo. The PNG ├ ─ ─ components | └ ─ ─ the HelloWorld. Vue ├ ─ ─ index. The HTML ├ ─ ─ the main, js └ ─ ─ vite. Config. JsCopy the code

Next, modify the logic in the timec page directive:

  • Locate thevite.config.jsLocation of the file
  • use--configSpecify the location of the configuration file
  • inspawnThe parameters of the configuration file are passed in to the called method
const cwd = path.resolve(__dirname, '.. / ');
const viteConfigPath = path.join(cwd, 'src/page/vite.config.js');
const serveService = spawn('node_modules/.bin/vite'['src/page'.'--host'.'--config', viteConfigPath], {
  cwd,
  stdio: 'inherit'});/ /... code
Copy the code

At this point, the basics of front-end engineering are set up, and the data needed to display the page is available through Node’s apis. There are two solutions:

  1. The page uses a SSR (server rendering) scheme
  2. Add a back-end service that passes the required data through an interface call

The project adopts the second solution. The following is a brief introduction to the construction of a simple back-end service

The service side

Here use your own DIY toy frame Flash – Wolves

Install dependencies

yarn add flash-wolves
Copy the code

Write the basic call logic and create a file server.js under SRC /page

  • useNodeWith these three lines of code, a simple back-end service is started on port 3001
const { Fw } = require('flash-wolves');
const app = new Fw();
app.listen(3001);
Copy the code

Write two interfaces:

  1. Obtaining a Configuration File
  2. Get all data (by day)
app.get('/json'.(req, res) = > {
  const config = getConfig();
  const { recordFilepath } = config;
  if (fs.existsSync(recordFilepath)) {
    res.success(getJSON(getFileContent(recordFilepath)));
    return;
  }
  res.fail(500.'not set default recordFilepath');
});

app.get('/config'.(req, res) = > {
  const config = getConfig();
  res.success(config);
});
Copy the code

When is this service started?

Of course, at the same time as starting the Web service

This requires us to add the logic to start the backend service in the timec Page directive:

  1. Use the samespawnCreate a child process to start the back-end service
  2. Kill the child process of the back-end service when the client service is shut down
const server = spawn('node'['src/page/server.js'], {
  cwd,
  stdio: 'inherit'}); serveService.on('close'.(code) = > {
  server.kill('SIGSTOP');
  process.exit(code);
});
Copy the code

How do clients access these interfaces? :

  1. To reduce project complexity, the FETCH method is called directly to fetch data from the back-end interface
  2. Create a separate filesrc/page/api.jsStore this logic
export function getConfig() {
  return fetch('http://localhost:3000/config');
}

export function getEveryDayData() {
  return fetch('http://localhost:3001/json').then((res) = > res.json());
}
Copy the code

The Web is restricted by the same origin policy. In this case, add the following logic to the Fw instantiation function to enable CORS to solve cross-domain problems

const app = new Fw((req, res) = > {
  / / open CORS
  const { method } = req;
  // Allow cross-domain
  res.setHeader('Access-Control-Allow-Origin', req.headers.origin);
  // Header types allowed across domains
  res.setHeader('Access-Control-Allow-Headers'.The '*');
  // Allow cookies across domains
  res.setHeader('Access-Control-Allow-Credentials'.'true');
  // Allowed methods
  res.setHeader('Access-Control-Allow-Methods'.'PUT, GET, POST, DELETE, OPTIONS');
  // Set the response header
  res.setHeader('Content-Type'.'application/json; charset=utf-8');
  // Request release for pre-inspection
  if (method === 'OPTIONS') {
    res.statusCode = 204; res.end(); }});Copy the code

So the simple front and back end logic is written, and the next is a button to start

timec page
Copy the code

The last

With limited free time per day, I’ll stop there and continue to refine the timec Page directive in the next installment

If you don’t have enough, stay tuned for updates, or keep an eye on the status of the warehouse

Welcome to comment section to raise demand, exchange discussion

This series will continue to be updated and iterated until the first generation of the product is completed

  • The warehouse address