亚洲乱码中文字幕综合,中国熟女仑乱hd,亚洲精品乱拍国产一区二区三区,一本大道卡一卡二卡三乱码全集资源,又粗又黄又硬又爽的免费视频

Vite項(xiàng)目自動(dòng)添加eslint prettier源碼解讀

 更新時(shí)間:2022年12月27日 15:55:32   作者:田八  
這篇文章主要為大家介紹了Vite項(xiàng)目自動(dòng)添加eslint prettier源碼解讀,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪

引言

vite-pretty-lint庫(kù)是一個(gè)為Vite創(chuàng)建的VueReact項(xiàng)目初始化eslintprettier的庫(kù)。

該庫(kù)的目的是為了讓開發(fā)者在創(chuàng)建項(xiàng)目時(shí),不需要手動(dòng)配置eslintprettier,而是通過vite-pretty-lint庫(kù)來自動(dòng)配置。

源碼地址:

使用

根據(jù)vite-pretty-lint庫(kù)的README.md,使用該庫(kù)的只需要執(zhí)行一行命令即可:

// NPM
npm init vite-pretty-lint
// YARN
yarn create vite-pretty-lint
// PNPM
pnpm init vite-pretty-lint

這里就涉及到了一個(gè)知識(shí)點(diǎn),npm init <initializer>,yarn create <initializer>,pnpm init <initializer>,這三個(gè)命令的作用是一樣的,都是用來初始化一個(gè)項(xiàng)目的。

<initializer>是一個(gè)初始化項(xiàng)目的包名,比如vite-pretty-lint就是一個(gè)初始化項(xiàng)目的包名;

執(zhí)行npm init vite-pretty-lint命令后,相當(dāng)于執(zhí)行npx create-vite-pretty-lint命令;

這里不多講解,參考:npm init

源碼閱讀

打開lib/main.js文件直接看,一開頭就看到了下面這段代碼:

const projectDirectory = process.cwd();
const eslintFile = path.join(projectDirectory, '.eslintrc.json');
const prettierFile = path.join(projectDirectory, '.prettierrc.json');
const eslintIgnoreFile = path.join(projectDirectory, '.eslintignore');

一看這些名字就知道,這里是用來創(chuàng)建eslintprettier的配置文件的,這里的projectDirectory就是當(dāng)前項(xiàng)目的根目錄。

當(dāng)然現(xiàn)在這些暫時(shí)還沒有用到,接著往下走:

async function run() {
    let projectType, packageManager;
    try {
        const answers = await askForProjectType();
        projectType = answers.projectType;
        packageManager = answers.packageManager;
    } catch (error) {
        console.log(chalk.blue('\n?? Goodbye!'));
        return;
    }
    // 省略后面代碼
}

一個(gè)run函數(shù),這個(gè)就是執(zhí)行命令的入口函數(shù),可以將代碼拉到最低下就知道了。

這里直接看askForProjectType函數(shù),這個(gè)函數(shù)是通過./utils.js文件來的,進(jìn)去看看

export function askForProjectType() {
  return enquirer.prompt([
    {
      type: 'select',
      name: 'projectType',
      message: 'What type of project do you have?',
      choices: getOptions(),
    },
    {
      type: 'select',
      name: 'packageManager',
      message: 'What package manager do you use?',
      choices: ['npm', 'yarn', 'pnpm'],
    },
  ]);
}

這里就是通過enquirer庫(kù)來獲取用戶的輸入,enquirer庫(kù)是一個(gè)命令行交互的庫(kù),可以參考:enquirer

這里只有兩個(gè)問題,一個(gè)是項(xiàng)目類型,一個(gè)是包管理器,包管理器就是npm,yarnpnpm;

項(xiàng)目類型是用過getOptions函數(shù)來獲取的:

export function getOptions() {
  const OPTIONS = [];
  fs.readdirSync(path.join(__dirname, 'templates')).forEach((template) => {
    const { name } = path.parse(path.join(__dirname, 'templates', template));
    OPTIONS.push(name);
  });
  return OPTIONS;
}

getOptions函數(shù)就是獲取templates文件夾下的所有文件夾,然后將文件夾名作為選項(xiàng)返回。

回到main.js文件,繼續(xù)往下看:

const {packages, eslintOverrides} = await import(`./templates/${projectType}.js`);
const packageList = [...commonPackages, ...packages];
const eslintConfigOverrides = [...eslintConfig.overrides, ...eslintOverrides];
const eslint = {...eslintConfig, overrides: eslintConfigOverrides};

當(dāng)用戶回答完問題后,就會(huì)根據(jù)用戶的選擇來導(dǎo)入對(duì)應(yīng)的模板文件,比如用戶選擇了react,那么就會(huì)導(dǎo)入./templates/react.js文件。

可以進(jìn)去templates文件夾里面的文件看看,這里是vue.js文件:

export const packages = ['vue-eslint-parser', 'eslint-plugin-vue'];
export const eslintOverrides = [
  {
    files: ['*.js'],
    extends: ['eslint:recommended', 'plugin:prettier/recommended'],
  },
  {
    files: ['*.vue'],
    parser: 'vue-eslint-parser',
    parserOptions: {
      ecmaVersion: 'latest',
      sourceType: 'module',
    },
    extends: [
      'eslint:recommended',
      'plugin:vue/vue3-recommended',
      'plugin:prettier/recommended',
    ],
    rules: {
      'vue/multi-word-component-names': 'off',
    },
  },
];

這里的packages就是需要安裝的包,eslintOverrides就是eslint的配置,這里的配置就是vue項(xiàng)目的eslint配置。

然后下面就是一些合并的配置,都是通過shared.js文件來的:

// shared.js
export const commonPackages = [
  'eslint',
  'prettier',
  'eslint-plugin-prettier',
  'eslint-config-prettier',
  'vite-plugin-eslint',
];
export const eslintConfig = {
  env: {
    browser: true,
    es2021: true,
    node: true,
  },
  overrides: [],
};

繼續(xù)往下看:

const commandMap = {
    npm: `npm install --save-dev ${packageList.join(' ')}`,
    yarn: `yarn add --dev ${packageList.join(' ')}`,
    pnpm: `pnpm install --save-dev ${packageList.join(' ')}`,
};
const viteConfigFiles = ['vite.config.js', 'vite.config.ts'];
const [viteFile] = viteConfigFiles
    .map((file) => path.join(projectDirectory, file))
    .filter((file) => fs.existsSync(file));
if (!viteFile) {
    console.log(
        chalk.red(
            '\n?? No vite config file found. Please run this command in a Vite project.\n'
        )
    );
    return;
}

這里就是通過commandMap來獲取對(duì)應(yīng)的安裝命令;

然后通過viteConfigFiles來獲取vite的配置文件;

這里是vite.config.js或者vite.config.ts,然后通過viteFile來判斷是否存在vite的配置文件;

沒有vite的配置文件就證明不是vite項(xiàng)目,然后程序結(jié)束。

繼續(xù)往下看:

const viteConfig = viteEslint(fs.readFileSync(viteFile, 'utf8'));
const installCommand = commandMap[packageManager];
if (!installCommand) {
    console.log(chalk.red('\n? Sorry, we only support npm、yarn and pnpm!'));
    return;
}

這里就是通過viteEslint來獲取vite的配置文件,然后通過installCommand來獲取對(duì)應(yīng)的安裝命令。

vimEslint也是在shared.js文件里面的:

export function viteEslint(code) {
  const ast = babel.parseSync(code, {
    sourceType: 'module',
    comments: false,
  });
  const { program } = ast;
  const importList = program.body
    .filter((body) => {
      return body.type === 'ImportDeclaration';
    })
    .map((body) => {
      delete body.trailingComments;
      return body;
    });
  if (importList.find((body) => body.source.value === 'vite-plugin-eslint')) {
    return code;
  }
  const nonImportList = program.body.filter((body) => {
    return body.type !== 'ImportDeclaration';
  });
  const exportStatement = program.body.find(
    (body) => body.type === 'ExportDefaultDeclaration'
  );
  if (exportStatement.declaration.type === 'CallExpression') {
    const [argument] = exportStatement.declaration.arguments;
    if (argument.type === 'ObjectExpression') {
      const plugin = argument.properties.find(
        ({ key }) => key.name === 'plugins'
      );
      if (plugin) {
        plugin.value.elements.push(eslintPluginCall);
      }
    }
  }
  importList.push(eslintImport);
  importList.push(blankLine);
  program.body = importList.concat(nonImportList);
  ast.program = program;
  return babel.transformFromAstSync(ast, code, { sourceType: 'module' }).code;
}

這里就是通過babel來解析vite的配置文件,然后通過importList來獲取import的配置,通過nonImportList來獲取非import的配置,通過exportStatement來獲取export的配置;

參考:babel

接著往下看:

const spinner = createSpinner('Installing packages...').start();
exec(`${commandMap[packageManager]}`, {cwd: projectDirectory}, (error) => {
    if (error) {
        spinner.error({
            text: chalk.bold.red('Failed to install packages!'),
            mark: '?',
        });
        console.error(error);
        return;
    }
    fs.writeFileSync(eslintFile, JSON.stringify(eslint, null, 2));
    fs.writeFileSync(prettierFile, JSON.stringify(prettierConfig, null, 2));
    fs.writeFileSync(eslintIgnoreFile, eslintIgnore.join('\n'));
    fs.writeFileSync(viteFile, viteConfig);
    spinner.success({text: chalk.bold.green('All done! ??'), mark: '?'});
    console.log(
        chalk.bold.cyan('\n?? Reload your editor to activate the settings!')
    );
});

通過nanospinner來創(chuàng)建一個(gè)spinner,參考:nanospinner

通過child_processexec來執(zhí)行安裝命令,參考:child_process

最后安裝完成,通過fs來寫入對(duì)應(yīng)的配置文件;

總結(jié)

通過學(xué)習(xí)vite-plugin-eslint,我們學(xué)習(xí)到了在vite項(xiàng)目中如何配置eslintprettier;

并且在這個(gè)過程中,我們學(xué)習(xí)到了如何通過viteplugin來實(shí)現(xiàn)對(duì)vite的擴(kuò)展;

還有這個(gè)項(xiàng)目的對(duì)vite的配置文件的解析,通過babel來解析vite的配置文件,然后通過importList來獲取import的配置,通過nonImportList來獲取非import的配置,通過exportStatement來獲取export的配置;

以上就是Vite項(xiàng)目自動(dòng)添加eslint prettier源碼解讀的詳細(xì)內(nèi)容,更多關(guān)于Vite添加eslint prettier的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

最新評(píng)論