从0开始搭建一个自己的react-app脚手架(webpack5+typescript)

从0开始搭建一个自己的react-app脚手架(webpack5+typescript)

1、前置工作

mkdir react-cli
cd react-cli
npm init --yes

此教程都是以yarn安装依赖的,npm、cnpm也可
平时我们可能自己写项目不常用eslint,、prettier等,在公司项目里这些也是很重要的,毕竟多人开发涉及到规范问题嘛,所以我们就先来配置eslint、prettier。

2、prettier eslint配置

yarn add prettier eslint -D 

新建一个.prettierrc文件
具体怎么配置的其实有很多中参数,可以去官网或者网上自己看看,我这边就只列出一点吧。

{
    "trailingComma": "none",//属性末尾不添加','
    "tabWidth": 2,  //缩进大小
    "semi": true,//是否添加分号
    "singleQuote": false, //是否单引号
    "endOfLine": "lf", //末尾留行
    "jsxSingleQuote": false, //jsx内属性是否单引号
    "printWidth": 120,
    "bracketSpacing": true, //在对象中个属性之间打印空格
    "arrowParens": "always" 
  }
  

这个配置文件有什么用呢,其实就是结合我们的vscode插件来进行保存时自动格式化,首先要安装插件Prettier哈,然后在文件下新建.vscode文件夹,在下面新建settings.json

{ 
    "search.exclude": {
      "**/node_modules": true,
      "dist": true,
      "yarn.lock": true
    },
    "editor.formatOnSave": true,
    "[javascript]": {
      "editor.defaultFormatter": "esbenp.prettier-vscode"
    },
    "[javascriptreact]": {
      "editor.defaultFormatter": "esbenp.prettier-vscode"
    },
    "[typescript]": {
      "editor.defaultFormatter": "esbenp.prettier-vscode"
    },
    "[typescriptreact]": {
      "editor.defaultFormatter": "esbenp.prettier-vscode"
    },
    "[json]": {
      "editor.defaultFormatter": "esbenp.prettier-vscode"
    },
    "[html]": {
      "editor.defaultFormatter": "esbenp.prettier-vscode"
    },
    "[markdown]": {
      "editor.defaultFormatter": "esbenp.prettier-vscode"
    },
    "[css]": {
      "editor.defaultFormatter": "esbenp.prettier-vscode"
    },
    "[less]": {
      "editor.defaultFormatter": "esbenp.prettier-vscode"
    },
    "[scss]": {
      "editor.defaultFormatter": "esbenp.prettier-vscode"
    }
  }

这样别人下你的脚手架就可以用你的配置了。到这你的prettier就配置完成啦
接下来我们配置eslint

npx eslint --init

执行npx eslint的时候会有选择让你一键生成配置文件很方便,我们就来看看各个问题吧。

  • 1、how would you like to use Eslint?
    我们选择第三条check syntax,find problem,and enforce code style
  • 2、What type of modules does your project use
    JavaScript modules (import/export)使用esmodule
  • 3、Which framework does your project use?
    果断react啊
  • 4、Does your project use TypeScript?
    果断ts
  • 5、Where does your code run?
    brower、node都要,因为我们还会使用到node中的模块.
  • 6、How would you like to define a style for your project?
    这个就选择use a popular style guide 受欢迎肯定不会错的啦,跟着大家走
  • 7、Which style guide do you want to follow?
    airbnb 不多说,大家都用它
  • What format do you want your config file to be in?
    这个就随便啦js,json,yaml差不多,这边我就选择js了

选完后,他会根据我们选择的配置安装依赖
初始化完成后我们的eslint.js就是这样子的啦

module.exports = {
  env: {
    browser: true,
    es2021: true,
    node: true,
  },
  extends: [
    'plugin:react/recommended',
    'airbnb',
  ],
  parser: '@typescript-eslint/parser',
  parserOptions: {
    ecmaFeatures: {
      jsx: true,
    },
    ecmaVersion: 12,
    sourceType: 'module',
  },
  plugins: [
    'react',
    '@typescript-eslint',
  ],
  rules: {
  },
};

这些配置还不够,我们还需要进行一些配置

extends: [
    "plugin:react/recommended",
    "plugin:eslint-plugin-react/recommended",
    "plugin:@typescript-eslint/recommended",
    "airbnb",
    "airbnb/hooks",
  ],
plugins: ["react", "unicorn", "@typescript-eslint",],
settings: {
    "import/resolver": {
      node: {
        extensions: [".tsx", ".ts", ".js", ".json"] //import index from './index'自动推导后缀
      },
      typescript: {}
    }
  }

当然还要配置我们的ruls,这其实配置不好就会很难受,很容易跟prettier发生冲突。我这边是这么配置的哈,其实配置这个的时候我也踩了不少坑。。都是一步一步走过来的。才的坑多了就有经验了。

"import/extensions": [
      ERROR,
      "ignorePackages",
      {
        ts: "never",
        tsx: "never",
        json: "never",
        js: "never"
      }
    ],
    "no-var": "error",
    "no-use-before-define": "off",
    "@typescript-eslint/explicit-module-boundary-types": 0,
    "react/jsx-filename-extension": [1, { extensions: [".tsx", ".ts"] }],
    "unicorn/prevent-abbreviations": "off",
    "comma-dangle": ["error", "never"],
    "import/no-unresolved": "error",
    "space-in-parens": "off",
    "spaced-comment": "off",
    "eol-last": "off",
    quotes: [0, "double"],
    semi: [2, "always"]

好了之后我这边的eslintrc.js就是这样子的啦

module.exports = {
  env: {
    browser: true,
    es2021: true,
    node: true
  },
  extends: [
    "plugin:react/recommended",
    "airbnb",
    "plugin:@typescript-eslint/recommended",
    "airbnb/hooks",
    "plugin:eslint-plugin-react/recommended"
  ],
  parser: "@typescript-eslint/parser",
  parserOptions: {
    ecmaFeatures: {
      jsx: true
    },
    ecmaVersion: 12,
    sourceType: "module"
  },
  settings: {
    "import/resolver": {
      node: {
        extensions: [".tsx", ".ts", ".js", ".json"]
      }
    }
  },
  plugins: ["react", "@typescript-eslint"],
  rules: {
    "no-var": "error",
    "no-use-before-define": "off",
    "@typescript-eslint/explicit-module-boundary-types": 0,
    "react/jsx-filename-extension": [1, { extensions: [".tsx", ".ts"] }],
    "unicorn/prevent-abbreviations": "off",
    "comma-dangle": ["error", "never"],
    "import/no-unresolved": "error",
    "space-in-parens": "off",
    "spaced-comment": "off",
    "eol-last": "off",
    quotes: [0, "double"],
    semi: [2, "always"]
  }
};

我们可以新建一个index.ts文件,然后我们可以随便写一点比如我们rules中有no-var就说明我们不能用var来声明变量,但是我们发现eslint中并没有报错,这是啥原因呢,害,其实很简单,重启一下试试?这边踩坑有点多我也记不得了哈哈,然后在安装个vscode的eslint插件,这样就有fix功能啦。eslint还可以使用命令行来进行检测,编写npm script,因为默认不检测tsx所以我们通过–ext来设置检测哪些后缀

"lint": "npm run lint-eslint",
"lint-eslint": "npx eslint src --ext .js,.ts,tsx",

接下来执行下yarn lint试下?eslint的配置就将讲到这里啦

3、webpack

上面说的都是补充内容,其实不配置问题也不大,自己用完全不用配置但是嘛规范还是要从小抓起的啦。话不多说开始我们的webpack配置,没有了解过的最好去了解一下webpack的基本使用。最基本的entry,output,loader,plugin懂了就可以啦。

yarn add webpack webpack-cli -D

新建一个src文件夹和一个build文件夹,src下就是平常我们写逻辑的啦,build文件下我们会写一些webpack的配置。
我们这边先新建一个webpack.config.js,这边会有个坑哈,我们因为选的是esmodule所以eslint会对commonjs报错,怎么解决呢,很简单配置个.eslingignore就行啦。webpack.config.js这里配置如下

const { ROOT_PATH } = require("../constant");
const path = require("path");
module.exports = {
  target: "web",
  entry: {
    app: path.resolve(ROOT_PATH, "./src/index.js")
  },
  output: {
    filename: `js/[name]:[hash:8].js`,
    path: path.resolve(ROOT_PATH, "./dist")
  }
};


这边还有一个constant文件,也是个基础配置文件,我直接新建在build下面了,内容如下

const path = require("path");
const ROOT_PATH = path.resolve(__dirname, "../");
module.exports = { ROOT_PATH };//ROOT_PATH就是我们的项目根目录啦

然后我们就开始我们的第一次打包,从配置文件可以看出我们的入口文件是src下的index
.js所以我们在src下新建一个index.js然后随便写点js就行啦,接下来在package.json下面写script

 "dev": "webpack --config ./build/config/webpack.config.js"

然后执行yarn dev试试我们就可以看到在根目录下产生了dist文件夹啦里面就有我们打包好的内容。
我们平时的环境至少都有两个,开发和生产环境吧这两个环境的配置有些相同又有些不同,所以我们就可以对其进行一些简单的封装,我们将webpack.config.js改成webpack.common.js来把它当作各个环境下的共同部分,然后在新建两个webpack.dev.js和webpack.prod.js来表示不同环境下的不同配置,然后根据不同的文件加载不同的配置文件即可,但是公共部分怎么加载呢,这里我们就需要使用webpack-merge了

yarn add webpack-merge -D

然后分别配置我们的两个配置文件吧

//webpack.dev.js
const common = require("./webpack.common");
const { merge } = require("webpack-merge");
module.exports = merge(common, {
  mode: "development"
});
//webpack.prod.js
const { merge } = require("webpack-merge");
const common = require("./webpack.common");
module.exports = merge(common, {
  mode: "production"
});

环境怎么区分呢?用过vuecli的可能会看到过一个变量叫做process.env.NODE_ENV,这是node的一个环境变量,NODE_ENV其实就是我们自己声明的区分不同环境的变量了,但是不同平台的声明方式不同,所以我们这里就又要使用了cross-env,他可以根据不同环境来声明我们的NODE_ENV,具体怎么做嘞,来看看

yarn add cross-env -D

修改我们的webpack.common.js

const { ROOT_PATH } = require("../constant");
const path = require("path");
const isDevelopment = process.env.NODE_ENV === "development" ? true : false;
module.exports = {
  target: "web",
  entry: {
    app: path.resolve(ROOT_PATH, "./src/index.ts")
  },
  output: {
    filename: `js/[name]${isDevelopment ? "" : ".[hash:8]"}.js`,
    path: path.resolve(ROOT_PATH, "./dist")
  }
};

上面做的操作就是如果是开发环境就不在打包文件后面添加哈希值,生产环境则添加。
然后重新写我们的npm script

 "dev": "cross-env NODE_ENV=development webpack --config ./build/config/webpack.dev.js",
    "build": "cross-env NODE_ENV=production webpack --config ./build/config/webpack.prod.js",

分别执行yarn dev、yarn build就可以看到区别啦。
我们可以发现每次打包之前的打包内容都还没清楚,这时候就需要我们的plugin了,这里我们使用clean-webpack-plugin插件

yarn add clean-webpack-plugin -D

修改webpack.common.js

const { ROOT_PATH } = require("../constant");
const { CleanWebpackPlugin } = require("clean-webpack-plugin");
const path = require("path");
const isDevelopment = process.env.NODE_ENV === "development" ? true : false;
module.exports = {
  target: "web",
  entry: {
    app: path.resolve(ROOT_PATH, "./src/index.ts")
  },
  output: {
    filename: `js/[name]${isDevelopment ? "" : ".[hash:8]"}.js`,
    path: path.resolve(ROOT_PATH, "./dist")
  },
  plugins: [new CleanWebpackPlugin()]
};

这下再次打包我们就会发现之前的打包内容都被清除啦。
之前用过vue-cli的肯定知道我们还会有个index.html,打包后的文件中有index.html,还会引入我们打包后的js,再一步还会在本地起一个server,这又是怎么实现的呢,一步一步来,首先我们在目录下见一个public目录下,这个文件下我们有一个index.html

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>react-cli</title>
  </head>
  <body>
    <div id="app"></div>
  </body>
</html>

我们写一个div并给一个id为app,为什么要这么做呢,熟悉vue或者react的肯定知道吧,这是我们挂载的根节点呀。怎么打包进dist呢?这时候就需要另一个插件啦,叫html-webpack-plugin

yarn add html-webpack-plugin -D

修改webpack.common.js

const { ROOT_PATH } = require("../constant");
const { CleanWebpackPlugin } = require("clean-webpack-plugin");
const HtmlWebpackPlugin = require("html-webpack-plugin");
const path = require("path");
const isDevelopment = process.env.NODE_ENV === "development" ? true : false;
module.exports = {
  target: "web",
  entry: {
    app: path.resolve(ROOT_PATH, "./src/index.js")
  },
  output: {
    filename: `js/[name]${isDevelopment ? "" : ".[hash:8]"}.js`,
    path: path.resolve(ROOT_PATH, "./dist")
  },
  plugins: [
    new CleanWebpackPlugin(),
    new HtmlWebpackPlugin({
      template: path.resolve(PROJECT_PATH, "./public/index.html"),
      filename: "index.html",
      cache: false //关闭缓存
    })
  ]
};

修改index.js

const dom = document.querySelector("#app");
dom.innerHTML = "hello,react";

这时候我们在执行一下yarn dev,就可以看到dist下有index.html,而且还引入了我们打包出来的js,如果你可以本地preview,就可以看到我们js执行的效果啦。
接下来就是在本地启服务啦,这里我们需要用到webpack的devserver了,

yarn add webpack-devserver -D

因为只有开发环境下需要启服务,所以我们就直接在webpack.dev.js下进行修改,很简单

const common = require("./webpack.common");
const { merge } = require("webpack-merge");
const path = require("path");
const { ROOT_PATH } = require("../constant");
module.exports = merge(common, {
  mode: "development",
  devServer: {
    overlay: true, //编译错误直接显示在页面上
    contentBase: path.resolve(ROOT_PATH, "./dist"),
    port: "3000", // 指定端口,默认是8080
    compress: true, // 是否启用 gzip 压缩
    open: true, // 打开默认浏览器
    hot: true // 热更新
  }
});

然后在修改我们的npm scripts

 "dev": "cross-env NODE_ENV=development webpack serve --config ./build/config/webpack.dev.js",

在执行yarn dev就可以啦,我们打开3030端口就可以看到页面啦

4、处理各种类型的文件

我们都知道webpack是将各个文件都当作一个模块的,默认是只能处理文件的,如果要处理如图片、css等文件就需要我们的loader啦

yarn add file-loader url-loader css-loader less-loader style-loader -D

file-loader和url-loader是处理图片等文件的,他可以将图片打包成静态文件,也可以打包成js文件,url-loader是基于file-loader的哈。接下来就配置我们的loader啦

const { ROOT_PATH } = require("../constant");
const { CleanWebpackPlugin } = require("clean-webpack-plugin");
const HtmlWebpackPlugin = require("html-webpack-plugin");
const path = require("path");
const isDevelopment = process.env.NODE_ENV === "development" ? true : false;
module.exports = {
  target: "web",
  entry: {
    app: path.resolve(ROOT_PATH, "./src/index.js")
  },
  output: {
    filename: `js/[name]${isDevelopment ? "" : ".[hash:8]"}.js`,
    path: path.resolve(ROOT_PATH, "./dist")
  },
  module: {
    rules: [
      {
        test: /.css$/,
        use: ["style-loader", "css-loader"]
      }
    ]
  },
  plugins: [
    new CleanWebpackPlugin(),
    new HtmlWebpackPlugin({
      template: path.resolve(ROOT_PATH, "./public/index.html"),
      filename: "index.html",
      cache: false
    })
  ]
};

loader的配置就如上图,其中use是一个数组,里面的执行的从后往前一次执行,所以一定要注意顺序哈!!对于css的处理我们就是css-style先执行,在执行style-loader。当然数组项可以是一个对象比如css-loader你也可以写成

  rules: [
      {
        test: /.css$/,
        use: [
          "style-loader",
          {
            loader: "css-loader",
            options: {
              modules: false,
              sourceMap: false
            }
          }
        ]
      }
    ]

我们可以在src下写个index.css,然后在index.js中import

//index.css
#app {
  color: red;
}
// index.js
import "./index.css";

const dom = document.querySelector("#app");
dom.innerHTML = "hello,react";

在执行yarn dev就能看到css效果啦,less也一样啦,配置loader即可,如果配置项不清楚可以查看文档哟。
对于图片文件我们也是一样处理的,使用的loader是file-loader和url-loader配置如下

 {
        test: [/\.jpg$/, /\.png$/, /\.gif$/],
        use: [
          {
            loader: "url-loader",
            options: {
              limit: 1024,
              name: "[name].[contenthash:8].[ext]",
              outputPath: "assets/images"
            }
          }
        ]
      },

上面url-loader的配置项意思是低于1024kb的就打包进入js文件里,否则保存在assets/images目录下

5、编译ts

浏览器是识别不了ts的啦,webpack自然也不行,毕竟他本来就是打包js的。所以我们就需要使用另一个神器 babel啦,话不多说先安装

yarn add @babel/core @babel/preset-env @babel/preset-typescript babel-loader -D

babel/core是babel的核心模块,babel/preset-env是用于降级js,因为部分浏览器还不支持es6语法就需要统一降为es5 ,babel/preset-typescript让ts编译成js的啦。 在本目录下建立配置文件.babelrc

{
    "presets": ["@babel/preset-env", "@babel/preset-typescript"]
  }

然后就可以配置loader啦,对ts、js、tsx等文件我们就都可以使用babel-loader来进行编译啦,配置跟上面的css一样

 {
        test: [/\.tsx$/, /\.js$/,/\.ts$/],
        exclude: /node_modules/, //不编译node_modules模块内里
        use: [
          {
            loader: "babel-loader",
            options: {
              cacheDirectory: true
            }
          }
        ]
      }

6、tsconfig.json

我们在用ts的时候经常会看到tsconfig.json文件,这个文件的作用呢,就是定义一些编译选项,指定编译文件,执行下面步骤就可以看到配置文件啦

npx tsc --init

这边放出部分配置

"compilerOptions": {
    "jsx":"react",
    "target": "es5",                                /* Specify ECMAScript     target version: 'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017', 'ES2018', 'ES2019', 'ES2020', or 'ESNEXT'. */
    "module": "commonjs",          
     "strict": true, 
    "moduleResolution": "node",               // 指定模块解析策略
    "esModuleInterop": true,                  // 支持 CommonJS 和 ES 模块之间的互操作性
    "resolveJsonModule": true,                // 支持导入 json 模块
    "baseUrl": "./",                          // 根路径
    "paths": {																// 路径映射,与 baseUrl 关联
      "@/*": ["src/*"]
    },
     "forceConsistentCasingInFileNames": true, // 禁止对同一个文件的不一致的引用
    "skipLibCheck": true,                     // 忽略所有的声明文件( *.d.ts)的类型检查
    "allowSyntheticDefaultImports": true,     // 允许从没有设置默认导出的模块中默认导入
    "noEmit": true
    },
    "exclude": ["node_modules"],

主要就是我们的paths路径讲解,我们写过vue的肯定知道脚手架中@代表的是src目录,所以我们这边也可以配置映射路径,当然这样子配置只能保证ts文件不报错,但是真正的映射还得是在webpack中配置
在webpack.common.js下配置

const { ROOT_PATH } = require("../constant");
const { CleanWebpackPlugin } = require("clean-webpack-plugin");
const HtmlWebpackPlugin = require("html-webpack-plugin");
const path = require("path");
const { resolve } = require("path");
const isDevelopment = process.env.NODE_ENV === "development" ? true : false;
module.exports = {
  target: "web",
  entry: {
    app: path.resolve(ROOT_PATH, "./src/index.ts")
  },
  output: {
    filename: `js/[name]${isDevelopment ? "" : ".[hash:8]"}.js`,
    path: path.resolve(ROOT_PATH, "./dist")
  },
  resolve: {
    extensions: [".tsx", ".ts", ".js", ".json"],
    alias: {
      "@": resolve(ROOT_PATH, "./src")
    }
  },
  module: {
    rules: [
      {
        test: /.css$/,
        use: [
          "style-loader",
          {
            loader: "css-loader",
            options: {
              modules: false,
              sourceMap: false
            }
          }
        ]
      },
      {
        test: [/\.js$/, /\.ts$/],
        exclude: /node_modules/,
        use: [
          {
            loader: "babel-loader",
            options: {
              cacheDirectory: true
            }
          }
        ]
      }
    ]
  },
  plugins: [
    new CleanWebpackPlugin(),
    new HtmlWebpackPlugin({
      template: path.resolve(ROOT_PATH, "./public/index.html"),
      filename: "index.html",
      cache: false
    })
  ]
};

当我们这样配置后发现eslint还是会报错,这时候我们就需要使用eslint-import-resolver-typescript

npm install eslint-import-resolver-typescript -D

在eslint配置文件中配置

settings: {
    "import/resolver": {
      node: {
        extensions: [".tsx", ".ts", ".js", ".json"]
      },
      typescript: {}
    }
  }

这样就可以啦.

7、React,React-dom配置

react核心两个包先安起来吧。

yarn add react react-dom
yarn add   @babel/preset-react -D

babel/preset-react是用来转换react语法的哈配置仍旧在babelrc里

{
    "presets": ["@babel/preset-env","@babel/react", "@babel/preset-typescript"]
  }

在写react语法之前我们要先将它的ts声明文件下载下来。

yarn add @types/react @types/react-dom -D

好了接下来就可以开始我们的react书写啦
我们现在src下新建一个index.tsx,App.tsx index.tsx这就是我们的入口文件啦,App.tsx就可以是我们的外层容器组件啦
App.tsx里就是我们熟悉的React语法啦

import React from "react";

const App = () => <div>hello React</div>;
export default App;

index.tsx则是我们挂载dom

import React from "react";
import ReactDom from "react-dom";
import App from "@/App";

ReactDom.render(<App />, document.querySelector("#app"));

是不是很熟悉,就是我们的react官方脚手架里的内容啦。我们自己搭的用法当然一样啦
接下来干啥呢,当然是修改我们的入口文件改为index.tsx啦,改好之后我们再yarn dev看下,发现报了个错没有loader处理tsx的错误,我们去配置文件里看下原来是忘记配置tsx了,加上就行啦,下面附上完整的webpack.common.js

const { ROOT_PATH } = require("../constant");
const { CleanWebpackPlugin } = require("clean-webpack-plugin");
const HtmlWebpackPlugin = require("html-webpack-plugin");
const path = require("path");
const { resolve } = require("path");
const isDevelopment = process.env.NODE_ENV === "development" ? true : false;
module.exports = {
  target: "web",
  entry: {
    app: path.resolve(ROOT_PATH, "./src/index.tsx")
  },
  output: {
    filename: `js/[name]${isDevelopment ? "" : ".[hash:8]"}.js`,
    path: path.resolve(ROOT_PATH, "./dist")
  },
  resolve: {
    extensions: [".tsx", ".ts", ".js", ".json"],
    alias: {
      "@": resolve(ROOT_PATH, "./src")
    }
  },
  module: {
    rules: [
      {
        test: /.css$/,
        use: [
          "style-loader",
          {
            loader: "css-loader",
            options: {
              modules: false,
              sourceMap: false
            }
          }
        ]
      },
      {
        test: [/\.js$/, /\.ts$/, /\.tsx$/],
        exclude: /node_modules/,
        use: [
          {
            loader: "babel-loader",
            options: {
              cacheDirectory: true
            }
          }
        ]
      },
      {
        test: [/\.png$/, /\.jpg$/, /\.jpeg$/, /\.gif$/, /\.svg$/],
        use: ["url-loader"]
      }
    ]
  },
  plugins: [
    new CleanWebpackPlugin(),
    new HtmlWebpackPlugin({
      template: path.resolve(ROOT_PATH, "./public/index.html"),
      filename: "index.html",
      cache: false
    })
  ]
};

好了,现在脚手架的基本实现就到这里啦。

8、补充

图片处理

上面讲file-loader,url-loader的时候忘记给例子了,这边我们就来给个例子,修改App.tsx

import React from "react";
import img from "@/1.png";

const App = () => <img src="./1.png" alt="" />;
export default App;

我们发现ts报错了,找不到png的类型声明,简言之图片也是模块,但找不到他的类型,这时候ts的声明文件就体现作用啦,我们在src下新建一个types文件夹,这里面就放我们的声明文件啦,新建index.d.ts,声明一下就可以啦

declare module "*.svg";
declare module "*.png";
declare module "*.jpg";
declare module "*.jpeg";
declare module "*.gif";
declare module "*.bmp";
declare module "*.tiff";

在执行yarn dev试试呀

编译的时候进行ts校验

执行上面的步骤后,你可以尝试故意写错一些ts的语法,你会发现ts明明报错了,但是webpack却还是正常编译了,这是咋回事,因为我们编译的时候呀是不进行ts语法校验的,这时候就可以使用另一个插件fork-ts-checker-webpack-plugin

yarn add fork-ts-checker-webpack-plugin -D

用法和之前插件一样引入后直接new实例就行啦

添加进度条

添加进度条需要我们使用webpackbar插件

yarn add webpackbar -D
new WebpackBar({
      name: isDevelopment ? "RUNNING" : "BUILDING",
      color: "#52c41a"
    })
终端只显示错误

我们现在yarn dev的时候还会现实编译问价内容,我们不需要显示,只需要现实错误就行啦,这里就需要在我们的dev-server下配置就行啦

 devServer: {
    stats: "errors-only", //只显示错误
    overlay: true, //编译错误直接显示在页面上
    contentBase: path.resolve(ROOT_PATH, "./dist"),
    port: "3000", // 指定端口,默认是8080
    compress: true, // 是否启用 gzip 压缩
    open: true, // 打开默认浏览器
    hot: true // 热更新
  }
错误显示在页面

我们的错误可以通过error-overlay-webpack-plugin插件直接显示在页面上,具体可以去github查看下效果,用法很简单,github上写的也很清楚

到这里我们的整个搭建过程就结束啦,有问题的可以+qq 547783781询问哦
仓库地址

9、参考

https://github.com/vortesnail/blog/issues/14

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值