不同前端工程目录中的各种配置文件

249 阅读14分钟

Vue

通过脚手架生成的Vue项目具备的配置文件如下:

  1. .gitgnore

  2. babel.config.js

  3. jsconfig.json

  4. package.json:管理项目所需的依赖库和工具。通过运行npm installyarn install命令,可以自动安装项目所需的依赖项。

  5. package-lock.json:自动生成的文件,用于确保在不同环境中安装相同版本的依赖项,以避免不同开发者之间的依赖不一致问题。会自动更新和生成。

  6. vue.config.js(可选):Vue Cli的配置文件,主要用于修改脚手架的默认配置,再根目录下的时候会被@vue/cli-service自动加载。例如开发服务器代理、配置插件、自定义构建输出目录等。

    • 使用

      使用说明
      publicPath: "/my-app"部署应用包时的基本URL,用法类似于webpack的output,publicPath
      outputDir: 'out'当运行 build 时生成的生产环境构建文件的目录,默认值dist,目标目录构建时会被清空,使用 -- no-clean可解决
      assetsDir:'source'放置生成的静态资源 (js、css、img、fonts) 相对于 outputDir 的目录。
      indexPath: 'html'指定生成的 index.html 的输出路径 (相对于 outputDir)。
      filenameHashing: true生成的静态资源在它们的文件名中包含了 hash 以便更好的控制缓存,使用 Vue CLI 生成的 index HTML,可以通过将这个选项设为 false 来关闭文件名哈希
      pages: object在 multi-page 模式下构建应用。每个“page”应该有一个对应的 JavaScript 入口文件。其值应该是一个对象,对象的 key 是入口的名字,value 是一个对象 指定了 entry, template, filename, titlechunks 的对象 (除了 entry 之外都是可选的); 或一个指定其 entry 的字符串。
      LintOnSave:是否在开发环境下通过 eslint-loader 在每次保存时 lint 代码。设置为 true'warning' 时,eslint-loader 会将 lint 错误输出为编译警告。默认情况下,警告仅仅会被输出到命令行,且不会使得编译失败。
      runtimeCompiler是否使用包含运行时编译器的 Vue 构建版本。
      transpileDependencies默认情况下 babel-loader 会忽略所有 node_modules 中的文件。你可以启用本选项,以避免构建后的代码中出现未转译的第三方依赖。
      productionSourceMap不需要生产环境的 source map,可以将其设置为 false 以加速生产环境构建
      crossorigin设置生成的 HTML 中 和
      integrity在生成的 HTML 中的 <link rel="stylesheet"><script> 标签上启用 Subresource Integrity (SRI)。如果你构建后的文件是部署在 CDN 上的,启用该选项可以提供额外的安全性
      configureWebpack如果这个值是一个对象,则会通过 webpack-merge 合并到最终的配置中。如果这个值是一个函数,则会接收被解析的配置作为参数。
      chainWebpack是一个函数,会接收一个基于 webpack-chainChainableConfig 实例。允许对内部的 webpack 配置进行更细粒度的修改。
      css.requireModuleExtension默认情况下,只有 *.module.[ext] 结尾的文件才会被视作 CSS Modules 模块。设置为 false 后你就可以去掉文件名中的 .module 并将所有的 *.(css
      css.sourceMap是否为 CSS 开启 source map。
      css.loaderOption向 CSS 相关的 loader 传递选项,支持的loader有css-loader、postcss-loader、sass-loader、less-loader、style-loader
      devServe所有 webpack-dev-server 的选项都支持
      devServer.proxy如果你的前端应用和后端 API 服务器没有运行在同一个主机上,你需要在开发环境下将 API 请求代理到 API 服务器。
      parallel是否为 Babel 或 TypeScript 使用 thread-loader。
      pluginOption传递第三方插件选项
  7. .eslintrc.js:eslint配置文件,检查和规范 JavaScript 代码

  8. .browserslistrc:配置目标浏览器和 Node.js 版本的范围

  9. postcss.config.js:PostCSS 是一个用于转换 CSS 的工具,通过配置可以指定需要使用的插件和转换规则。

Angular

通过angular/cli生成的项目中包含的配置文件如下:

  • .gitgnore
  • angular.json
  • package.json
  • tsconfig.json

tsconfig.json

如果一个目录下存在一个tsconfig.json文件,那么它意味着这个目录是TypeScript项目的根目录。 tsconfig.json文件中指定了用来编译这个项目的根文件和编译选项。

include,exclude,files

"include"指定一个包含相对或绝对文件路径的列表,相当于一个白名单"exclude"相当于一个黑名单,常用方法是用来排除"node_modules" 目录下的文件。

"include""exclude"属性指定一个文件glob匹配模式列表。 支持的glob通配符有:

  • * 匹配0或多个字符(不包括目录分隔符/
  • ? 匹配一个任意字符(不包括目录分隔符/
  • **/ 递归匹配任意子目录
{
    "compilerOptions": {
        ...
    },
    include: ["./src/**/*", "./demo/**/*.tsx?"],
    exclude: ["node_modules/**/*"]
}

"files"类似于"include",区别是不能使用通配符,必须使用精确的文件路径。用于指示哪些文件需要编译,可以添加一组文件路径,支持相对路径和绝对路径,相对路径是相对于项目根目录的。

{
    "compilerOptions": {
        ...
    },
    // include: ["./src/**/*", "./demo/**/*.tsx?"],
    // exclude: ["node_modules/**/*"]
    files: ['./src/index.ts']
}
hello@hello
extends配置

extends 用于在一个tsconfig.json文件中扩展其他tsconfig.json文件,

compilerOption配置
  1. increate :开启后只编译修改过的文件,这个时候会生成tsconfig.tsbuildinfo,下次编译的时候会进行对比只编译修改过的文件。

  2. target指定 ECMAScript 目标版本

  3. lib:用来设置需要引入的全局类型声明,他的默认值通过target来指定。

  4. module:编译后的JS使用的模块系统。target是ES3或ES5默认值为CommonJS。

  5. baseUrl:用于设置基础的URL,省略路径的前缀。

  6. paths:用于路径重映射,首先设置好baseUrlpaths的源路径和新路径会根据baseUrl作为相对路径计算。

  7. declaration:是否给每个编译出来的JS文件生成对应的d.ts文件.

  8. declarationDir: 指定编译生成的类型声明输出的目录,默认和生成的js文件在一起。

  9. outDir:编译文件的输出目录,默认项目根目录,通常设置为"./dist"

  10. outFile: 将所有的ts文件合并编译生成一个js文件和他对应的类型声明d.ts文件。

  11. allowJS:将JS文件也作为编译对象,可以被ts文件引入。默认值false

  12. allowUnreachableCode:是否允许代码中出现永远无法被执行到的代码, 可选值是undefined, false, true

  13. allowUnusedLabels :是否允许未使用到的标签,可选值:

    • undefined: 这是默认值, 碰到未使用的标签给出warning警告
    • false: 碰到未使用的标签抛出错误, 编译失败
    • true: 碰到未使用的标签编译通过, 且不给出异常
  14. alwaysStrict:是否保证输出的js代码处于严格模式。默认为true。

  15. exactOptionalProperties :ts4.4加入的新选项,默认不开启。开启选项会对可空属性执行更严格的类型检查, 可空属性只有在初始化时可以留空为undefined, 但是不能被手动设置为undefined

  16. downlevelIteration:开启选项后,typescript会生成帮助方法来ES6中的for of等语法进行转义。

  17. importHelpers:上面介绍了compilerOptions.downlevelIteration选项, 开启后会对for...of之类的迭代语法糖进行downleveling; typescript进行downleveling时, 会生成一些辅助方法, 默认情况下, 这些辅助代码是会直接插入到文件中对应的位置的, 这会生成的javascript存在重复的辅助方法从而造成代码文件体积过大的问题.开启compilerOptions.importHelpers后, 不在插入具体的辅助方法的代码到对应的位置, 而是通过模块导入来引用typescript的辅助方法

  18. strict :是一个strict相关标志位的总开关。设置为true会启用全部compilerOptions.strict开头的选项和其他相关的选项

  19. strictBindCallApply :开启选项后调用函数对象的bind、call、apply等方法时,typescript会执行参数的类型检查。

  20. strictFunctionTypes:开启此选项会进行严格的函数类型检查

const foo = (a: string) => {
  console.log(a);
}

interface Bar {
  (a: string | string[]): void;
}

// 开启 compilerOptions.strictFunctionTypes, 报错
// Type '(a: string) => void' is not assignable to type 'Bar'.
const bar:Bar = foo;

// 修改
const foo = (a: string) => {
  console.log(a);
}
interface Bar {
  (a: string): void;
}
const bar:Bar = foo;
  1. strictNullChecks :让typescript进行严格的null检查
  2. strictPropertyInitialization : 严格的对象初始化检查
  3. noImplicitAny :开启此选项后, 如果你声明一个没有标注类型的变量, 编译器会会给你一个编译时错误
  4. noImplicitOverride :开启此选项保证**子类重写基类的方法时, 必须在方法前加上****override**关键词。正确写法如下:
class A{
    build() {}
}
class B extends A{
    override build() { }
}
  1. noImplicitReturns : 开启该选项要求所有的选择分支都返回一致的类型
  2. noImplicitThis : 开启该选项禁止调用any类型的this
  3. noPropertyAccessFromIndexSignature :开启后禁止通过访问常规属性的方法来访问索引签名声明的属性。
class Color {
    r = 255;
    g = 255;
    b = 255;

    [key: string]: string | number;
}

const c = new Color();

console.log(c.r, c.g, c.b);

// 开启 compilerOptions.noPropertyAccessFromIndexSignature 的情况下,会有编译时错误:
// Property 'foo' comes from an index signature, so it must be accessed with ['foo'].
console.log(c.foo);
  通过传统的`"."` 符号访问属性,很容易出现属性`"undefined"`的异常,即使开启了`strictNullChecks`编译仍能通过, 但是运行就会发生异常。
  1. noUncheckedIndexedAccess : 开启这个选项会自动在索引签名语法声明的属性后补一个undefined类型。和上一个配置选项的目的可以达成一致。
  2. noUnusedLocals :判断是否存在未使用的局部变量
  3. noUnusedParameters :判断是否存在未使用的函数参数
  4. useUnknownInCatchVariables : 开启这个选项typescript会将catch语法块中的err变量当做unknown来处理, 不开启此选项时, err变量是被当做any类型来处理的, 这很容易造成经典的read property of undefined运行时异常
const doSomething = () => {
  throw Error("erro");
}
const fun = () => {
  try {
    doSomething();
  }catch(e)=> {
    console.error(e, e.error.message)
  }
}
fun()

Babel

介绍

Babel是一个js的编译器,主要将ES5+版本的JS代码转换为向后兼容的JS语法,以便可以在当前或旧版本的浏览器中运行。

主要的作用:转换语法、Ployfill目标环境中缺少的功能、源代码转换等

@babel/core

Babel 的核心功能容纳于 @babel/core 模块,可以在js中直接通过require的方式使用。 - 创建一个babel.config.json 文件,包含presets和plugins。

{
  "presets": [],
  "plugins": []
}
- 安装:`npm install @babel/core` 
- 执行babel编译 `npx babel index.js  --out-file output.js`,发现没有任何效果。
@bable/cli

@babel/cli 是一个允许你在终端使用 babel 的工具

plugins & presets

babel是基于插件架构的,我们可以编写自己的插件来指示转换,也可以使用官方插件,例如:@babel/plugin-transform-arrow-functions

"plugins": [
    "@babel/plugin-transform-arrow-functions",
  ]

为了解决我们逐一添加需要插件的繁琐,官方提供了很多的presets(包含了一组预先设置的插件)。比如preset-env(处理es6+规范语法的插件集合)、preset-stage(处理尚处在提案语法的插件集合)、preset-react(处理react语法的插件集合)等。

preset-env:使用es6的语法去写代码,并且只转换需要转换的代码。默认情况下preset-env什么都不需要配置,也可以提供一个targets配置项指定运行环境:

"presets": [
    [
      "@babel/preset-env",
      {
        "targets": {
          "ie": "8"
        }
      }
    ]
  ],
@babel/polyfill

对于ES6+新增的api,我们可以通过ployfill来进行转换。preset-env添加一个useBuiltIns配置项用来进行按需引入不支持api的polyfill

import '@babel/polyfill'
const fn = () => {}
new Promise(() => {})

其中,useBuiltIns entry | usageuseBuiltIns的值为usage时,它会扫描代码,只有代码用到的新的api,它才会引入相应的polyfill,这时需要core-js通过选项添加和设置版本corejs

@babel/runtime

有时候语法的转换相对复杂,可能需要一些helper函数,如转换es6的class。@babel/runtime提供了各种各样的helper函数,事实上babel提供了一个@babel/plugin-transform-runtime插件帮我们自动引入helper。我们首先安装@babel/runtime@babel/plugin-transform-runtime

npm install @babel/runtime @babel/plugin-transform-runtime

修改plugins:

 "plugins": [
    "@babel/plugin-transform-runtime"
  ]  

再来看编译后的文件,里面的_classCallCheck辅助函数已经是从@babel/runtime引入的了。

事实上@babel/plugin-transform-runtime还有一个更重要的功能,它可以为你的代码创建一个sandboxed environment(沙箱环境),@babel/plugin-transform-runtime给我们提供了一个配置项corejs,它可以将这些变量隔离在局部作用域

Babel如何合并配置项?

当选项存在且不为undefined时,进行覆盖。

特殊地:

  • assumptions, parserOptsgeneratorOpts, 对象被合并,而不是被替换。
  • plugins and presets, 则根据 plugin/preset object/function 本身的标识结合入口的名称来替换它们。
  • 举例
// before
{
  sourceType: "script",
  assumptions: {
    setClassFields: true,
    iterableIsArray: false
  },
  env: {
    test: {
      sourceType: "module",
      assumptions: {
        iterableIsArray: true,
      },
    }
  }
};

// after,当 NODE_ENV  test, sourceType 选项将被替换,assumptions 选项将被合并。
{
  sourceType: "module",
  assumptions: {
    setClassFields: true,
    iterableIsArray: true,
  },
};

Eslint

介绍

ESLint 是一个根据方案识别并报告 ECMAScript/JavaScript 代码问题的工具,其目的是使代码风格更加一致并避免错误。

基本使用 ,可以 - - config选择托管在npm上的共享配置。

 npm init @eslint/config

ESLint 配置的主要内容包括 执行环境 ****env规则 rules 以及插件**plugins**

环境配置

环境会提供预设的全局变量,如browser、node、es6等。同时可以使用插件中的环境。配置文件如下:

{
    "env": {
        "browser": true,
        "node": true
    }
}
全局变量

env 可以方便地支持特定环境下的全局变量,但 JavaScript 的执行环境要复杂得多,每个模块和外部依赖都有可能注入自己的全局变量,为了避免这被识别成错误,需要在配置中指出代码中用到的外部全局变量。globals字段用于设置代码中的全局变量,语法为{"var_name": "off"|"readonly"|"writable"}, 如:

{
  "env":{
    "es6": true
  },
  "globals":{
    "Promise":"off"
  }
}
规则

规则是 ESLint 的核心构建模块。EsLint 有大量的内置规则,可以通过插件添加更多规则。也可以通过配置注释或配置文件来修改项目使用哪些规则。

规则对应的设置值为这些值之一:

  • "off"0 - 关闭规则
  • "warn"1 - 启用并视作警告(不影响退出)。
  • "error"2 - 启用并视作错误(触发时退出代码为 1)

如果需要使用插件规则,需要在规则ID前加上插件名称和/

{
    "plugins": [
        "plugin1"
    ],
    "rules": {
        "eqeqeq": "off",
        "curly": "error",
        "quotes": ["error", "double"],
        "plugin1/rule1": "error"
    }
}

对于某些规则的禁用,可以使用配置注释。如eslint-disable-lineeslint-disable-next-line等。注意:禁用文件一部分警告的注释会让 ESLint 不报告禁用部分代码违反规则。然而,ESLint 仍会解析整个文件,所以禁用部分的代码仍需是语法上有效的 JavaScript

同时,可以使用overrides和files来对某一组的文件规则进行禁用。

{
  "rules": {...},
  "overrides": [
    {
      "files": ["*-test.js","*.spec.js"],
      "rules": {
        "no-unused-expressions": "off"
      }
    }
  ]
}
插件 & 解析器

默认情况下eslint使用espree作为解析器,我们可以使用指定的解析器,与eslint兼容的解析器有:

安装插件之后,就可以在 ESLint 的plugins数组中添加该配置文件需要使用的插件。不过,插件的各项规则配置都是默认关闭的,所以plugins只是使用插件功能的前提,必须在rules,extends,env中开启你需要的规则特性。举例:

{
  "plugins":["jest"],
  "extends": ["plugin:jest/recommended"],
  "env":{
    "jest/global":true
  },
  "rules":{
    "jest/valid-expect": "error"
  }
}

ESlint对插件进行了命名规定: - eslint-plugin-<plugin-name> 缩写 <plugin-name>: 如eslint-plugin-jquery 缩写 jquery。 - @<scope>/eslint-plugin-<plugin-name> 缩写 @<scope>/<plugin-name>: 如 @jquery/eslint-plugin-jquery 缩写 @jquery/jquery。 - @<scope>/eslint-plugin 缩写 @<scope>: 如 @jquery/eslint-plugin 缩写 @jquery

配置层级和规则合并

尽管一个目录下只有一个配置文件会生效,但 ESLint 支持在不同目录层级下放置多个配置文件。执行文件 lint 时,会从当前文件的目录开始,逐级往上查找配置文件,直到根目录或 遇到{"root": true}的配置,并合并不同层级的配置。

配置的优先级:

  • 配置类型上: 注释 > 命令行参数 > 配置文件
  • 文件层级上:(相对目标文件)近 > 远
  • 同一目录内:(只会采用一个配置文件)js > cjs > yaml > yml > json > package.json
  • 同一配置内:overrides > rule > extends
  • 同一选项内:后者 > 前者