源碼共讀-UMI-3

接上一個博客源碼共讀-UMI-2,接下來,我們來繼續執行 umi generate
第一個博客中我們知道,執行umi generate 會執行lib/scripts/ generate.js

lib/scripts/generate.js

import yParser from 'yargs-parser';
import generate from '../generate';

const argv = yParser(process.argv.slice(2));
const [type, file] = argv._;

generate({
  type,
  file,
  useClass: argv.c || argv.class || false,
  isDirectory: argv.d || argv.directory || false,
});

取出參數調用generate

../generate.js

import assert from 'assert';
import page from './generators/page';

const generators = {
  page,
};

這裏應該是爲了後續擴展使用的,這裏暫時只有一個page

export default function(opts = {}) {
  const { type, file } = opts;
  assert(type, 'opts.type should be supplied');
  assert(typeof type === 'string', 'opts.file should be string');
  assert(file, 'opts.file should be supplied');
  assert(typeof file === 'string', 'opts.file should be string');
  assert(generators[type], `generator of type (${type}) not found`);

  delete opts.type;
  generators[type](opts);
}

./generators/page

import assert from 'assert';

該模塊用於編寫應用程序的單元測試

import ejs from 'ejs';

嵌入式JavaScript模板

import uppercamelcase from 'uppercamelcase';

首字母大寫轉換 如 foo-bar => FooBar

import { join, basename } from 'path';
import { existsSync, statSync, readFileSync, writeFileSync } from 'fs';
屬性 說明
existsSync 測試某個路徑下的文件是否存在
statSync 獲取文件信息
readFileSync 讀取文件
writeFileSync 寫文件
//目錄存在
function directoryExists(path) {
  return existsSync(path) && statSync(path).isDirectory();
}
//文件存在
function fileExists(path) {
  return existsSync(path) && statSync(path).isFile();
}
//去除空行
function stripEmptyLine(content) {
  const ret = content
    .trim()
    // 兩行 -> 一行
    .replace(/\n\n/g, '\n');

  // 結尾空行
  return `${ret}\n`;
}
//看一下代碼時,可先忽略assert
export default function(opts = {}) {
  const { file } = opts;
  //斷言
  assert(
    !('isDirectory' in opts) || typeof opts.isDirectory === 'boolean',
    'opts.isDirectory should be boolean',
  );
  assert(
    !('useClass' in opts) || typeof opts.useClass === 'boolean',
    'opts.useClass should be boolean',
  );
  //目錄
  const isDirectory = opts.isDirectory || false;
  //當前執行路徑
  const cwd = opts.cwd || process.cwd();

  console.log(`[DEBUG] generate page ${file} with isDirectory ${isDirectory}`);

  let cssTargetPath;
  let jsTargetPath;
//是目錄的時候,在file目錄下新建page文件
//不是目錄的時候,新建file文件
  if (isDirectory) {
    assert(
      !directoryExists(join(cwd, 'src', 'page', file)),
      `directory src/page/${file} exists`,
    );
    jsTargetPath = join(cwd, 'src', 'page', file, 'page.js');
    cssTargetPath = join(cwd, 'src', 'page', file, 'page.css');
  } else {
    jsTargetPath = join(cwd, 'src', 'page', `${file}.js`);
    cssTargetPath = join(cwd, 'src', 'page', `${file}.css`);
  }

  assert(!fileExists(jsTargetPath), `file src/page/${file} exists`);
  assert(!fileExists(cssTargetPath), `file src/page/${file} exists`);

  //從模板中讀取文件
  const jsTpl = readFileSync(
    join(__dirname, '../../template/page.js'),
    'utf-8',
  );
  const cssTpl = readFileSync(
    join(__dirname, '../../template/page.css'),
    'utf-8',
  );


  const fileName = basename(file);
  const componentName = uppercamelcase(fileName);
  //使用ejs render文件
  //ejs.render(str, data, options);
  //options https://www.npmjs.com/package/ejs#options
  const jsContent = ejs.render(
    jsTpl,
    {
      useClass: opts.useClass,
      fileName,
      componentName,
    },
    {
      _with: false,
      localsName: 'umi',
    },
  );

  const cssContent = ejs.render(
    cssTpl,
    {},
    {
      _with: false,
      localsName: 'umi',
    },
  );

  //寫入文件
  writeFileSync(jsTargetPath, stripEmptyLine(jsContent), 'utf-8');
  writeFileSync(cssTargetPath, stripEmptyLine(cssContent), 'utf-8');
}

本節課就到此結束了,喜歡我的博客的朋友可以關注我。後續會有實戰演練哦。
Github地址
https://github.com/xiaohuoni/source-code-co-reading-umi

感謝您的閱讀。
我是莽夫,希望你開心。
如果你覺得本文對你有幫助,請掃描文末二維碼,支持博主原創。
希望大家關注我的個人公衆號ionic_
這裏寫圖片描述

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章