webpack从0开始搭建一个react+ts项目

一、前言

一般我们创建react项目都是通过create-react-app直接创建的,但是create-react-app创建之后,一些webpack配置并没有暴露出来,我们要是想更改webpack的话,还是比较麻烦的,因此本文主要是利用webpack开始搭建一个react项目。

二、项目初始化

1. 运行命令初始化package.json

yarn init
复制代码

或者

npm init
复制代码

如果想要加上默认配置的话,使用

npm init -y 或者 yarn init -y
复制代码

这两种初始化都可以,主要区别是yarn安装的速度更快一点,使用yarn的时候,会自动生成yarn.lock来锁定版本,而npm5.0以后是通过package-lock.json来锁定版本的,并且yarn 的语义化更好一点。

截屏2022-06-06 上午11.25.56.png

截屏2022-06-06 上午11.27.16.png

2. 安装webpack

yarn add webpack webpack-cli -D
复制代码

webpack是打包代码依赖的核心内容,而webpack-cli是一个用来在命令行中运行webpack的工具,webpack从4.0版本开始,就必须要同时安装webpack-cli。

3. 配置入口

入口文件指示webpack应该使用哪个文件来作为构建内部依赖图的开始,可以配置单个入口文件,也可以配置多个入口文件,具体语法详见:入口配置。本文这里只配置单入口。 新建一个src文件夹,里面新建一个文件 index.js,然后新建一个文件 webpack.config.js,里面配置入口文件entry。

截屏2022-06-06 下午1.45.03.png

4. 配置出口

出口文件即告诉webpack在哪输出它所创建的那些文件,以及如何命名这些输出的文件,默认值为./dist。出口配置里面的filename用于输出文件的文件名,path是输出目录的绝对路径。 截屏2022-06-06 下午1.44.23.png

5. 区分环境

一般项目都需要区分是开发环境还是线上环境,因此安装cross-env来区分环境。

yarn add cross-env -D
复制代码

安装好了之后,具体的文件里面可以通过 process.env.NODE_ENV 来判断当前的环境。

6. 配置loader

因为webpack自身只理解js,所以loader是让webpack可以处理那些非js类型的文件,可以将所有类型的文件转化为webpack能够理解的有效模块。loader主要是有两个属性,test属性和use属性,test属性用于标识出应该被对应的 loader 进行转换的某个或某些文件, use 属性,表示进行转换时,应该使用哪个 loader。

截屏2022-06-06 下午1.57.03.png

7. 配置plugin

plugin表示的是插件,插件功能非常多,可以用来处理各种各样的任务,主要是为了解决loader无法实现的其他事。

截屏2022-06-06 下午4.11.42.png

三、项目配置

1. 创建首页页面

webpack打包出来的都只有js文件,使用 html-webpack-plugin 可以自定义一个html模板,最终html文件会被打包到 dist文件夹,并且也会把打包好的js文件引入。

yarn add html-webpack-plugin -D
复制代码

在src下面创建一个index.html,webpack.config.js配置如下:

截屏2022-06-06 下午4.52.37.png

2. 配置项目启动

可以安装下webpack-dev-server,这样每次项目更改的时候,浏览器都可以自动刷新。

yarn add webpack-dev-server -D
复制代码

接着配置下webpack.config.js,加下运行的端口 截屏2022-06-06 下午4.34.40.png 最后在package.json里面设置下启动命令

截屏2022-06-06 下午4.36.03.png

3. 安装react以及babel相关插件

@babel/core是babel的核心模块,@babel/preset-env内预设不同环境的语法转化插件,默认将es6转化为es5。

yarn add react react-dom
yarn add @babel/core
yarn add @babel/preset-env @babel/preset-react babel-loader
复制代码

4. 启动react项目

首先设置一个index.html

截屏2022-06-06 下午4.49.56.png 然后将index.js改成react语法形式

截屏2022-06-06 下午4.50.55.png 接着运行 yarn start 即可运行成功

截屏2022-06-06 下午4.51.42.png

5. 增加样式配置

样式文件需要增加loader,首先安装css-loaderstyle-loader

yarn add css-loader style-loader -D
复制代码

webpack.config.js 增加对css文件的loader配置,注意style-loader要写在css-loader前面,因为style-loader是将解析后的内容插入到页面,让样式生效,css-loader是解析css,需要先解析再插入,所以css-loader放最右边,先执行。

截屏2022-06-06 下午5.06.21.png 有时候根据项目的不同,我们可能会写.less或者.scss的样式文件,以.less为例,我们需要增加less的识别配置,首先安装lessless-loader插件。

yarn add less less-loader -D
复制代码

webpack.config.js增加配置如下:

截屏2022-06-06 下午5.12.21.png 由于这里没有把css 和 html 分开,所以打包的时候,是把样式用style形式嵌入到页面的,我们可以引入单独打包css的plugin,将css样式单独打包,然后通过外部引用进来。

yarn add mini-css-extract-plugin -D
复制代码

webpack.config.js配置如下,需要注意的是MiniCssExtractPlugin取代了原来的style-loader的位置,不需要再使用style-loader了

截屏2022-06-06 下午5.26.01.png 引入mini-css-extract-plugin前: 截屏2022-06-06 下午5.17.56.png 引入mini-css-extract-plugin后: 截屏2022-06-06 下午5.24.40.png 给样式配置通用前缀,引入 postcss-loaderautoprefixer

yarn add postcss-loader autoprefixer -D
复制代码

webpack.config.js增加配置如下: 截屏2022-06-07 下午5.12.49.png 最后效果图: 截屏2022-06-07 下午5.13.22.png

6. 配置字体、图片以及文件

项目里经常会出现字体以及图片,因此需要对字体和图片引入特定的loader来配置,此处安装url-loader来进行配置,url-loaderfile-loader有依赖,所以也需要安装下file-loader

yarn add url-loader file-loader -D
复制代码

webpack.config.js增加配置如下:(注意:本文的webpack版本为5.0以上,webpack5的url-loader,file-loader已经弃用,webpack5改用的是asset-module,如果想要继续使用的话,需要在use后面加上type: 'javascript/auto',url-loader默认采用ES模块语法,即import '…/aaa.png', 如果在引入css文件时是comandjs语法就会报错require('./css/normal.css'),所以需要将esModule设置为false,本文的图片是新建了一个public文件夹,然后在public文件夹里面还新建了一个images文件夹来放图片,所以include写的是我自己的图片路径,可按照需要改成你自己的图片路径

截屏2022-06-06 下午6.34.18.png 运行yarn run build,打包后的效果如下图所示:

截屏2022-06-06 下午6.31.18.png 页面如果要通过img来引入图片的话,可以通过require来导入:

<img src={require('./assets/images/cat.png')} />
复制代码

四、项目优化

1. 分环境配置webpack

基于以上两步,我们搭建了一个基本的 webpack+ react的环境,但是上述搭建起来的项目过于简单,针对以上搭建的,我们可以进一步优化,首先将webpack按照环境来分开配置,分成开发环境和线上环境。 首先安装插件,用来合并webpack之间的配置。

yarn add webpack-merge -D
复制代码

根目录下新建文件夹webpack,然后新建三个文件,webpack.config.js webpack.dev.js webpack.prod.js。

  • webpack.config.js配置如下
const path = require("path");
const HtmlWebpackPlugin = require("html-webpack-plugin");
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
module.exports = {
  entry: {
    app: "./src/index.js",
  },
  output: {
    path: path.resolve(__dirname, "../dist"),
    filename: "[name].bundle.js",
    clean: true
  },
  module: {
    rules: [
      {
        test: /\.js$/,
        exclude: /node_modules/,
        use: {
          loader: "babel-loader",
          options: {
            presets: ["@babel/preset-react"],
          },
        },
      },
      {
        test: /\.(css|less)$/,
        exclude: /node_modules/,
        use: [
          { loader: MiniCssExtractPlugin.loader },
          "css-loader",
          "less-loader",
        ],
      },
      {
        test: /\.(png|jpe?g|gif|svg)(\?.*)?$/,
        exclude: /node_modules/,
        include: [path.resolve("./public/images")],
        use: [
            {
                loader: 'url-loader',
                options: {
                    limit: 8192,
                    esModule: false
                }
            }
        ],
        type: 'javascript/auto'
      },
    ],
  },
  plugins: [
    new HtmlWebpackPlugin({ template: "./src/index.html" }),
    new MiniCssExtractPlugin(),
  ],
  devServer: {
    port: 8000,
    open: true,
  },
};
复制代码
  • webpack.dev.js 配置如下
const webpack = require("webpack");
const webpackMerge = require("webpack-merge");
const baseConfig = require("./webpack.config");

const config = {
  mode: "development",
  cache: {
    type: "memory", // 使用内存缓存
  },
};

const mergedConfig = webpackMerge.merge(baseConfig, config);
module.exports = mergedConfig;
复制代码
  • webpack.prod.js 配置如下
const webpack = require("webpack");
const webpackMerge = require("webpack-merge");
const baseConfig = require("./webpack.config");

const config = {
  mode: "production",
  cache: {
    type: "filesystem",
    buildDependencies: {
      config: [__filename], //使用文件缓存
    },
  },
  optimization: {
    minimize: true,
    moduleIds: "deterministic",
  },
};

const mergedConfig = webpackMerge.merge(baseConfig, config);
module.exports = mergedConfig;
复制代码
  • package.json里面的配置更改如下:
"scripts": {
    "build": "webpack --config webpack/webpack.dev.js",
    "build:prod": "cross-env NODE_ENV=production webpack --config webpack/webpack.prod.js",
    "start": "webpack serve --config webpack/webpack.dev.js"
  },
复制代码

当前目录如下:

截屏2022-06-07 上午11.20.49.png

2. 优化src的目录结构

src目录更改如下:

  • 新建 assets 文件夹,用来存放静态资源,比如图片和字体文件
  • 新建 components 文件夹,用来存放组件
  • 新建 pages 文件夹,用来存放页面文件
  • 新建 routes 文件夹,用来存放路由
  • 新建 api 文件夹,用来存放接口请求文件
  • 新建 App.js,设置主页面
  • src里面原有的index.html迁移到public.html里面

截屏2022-06-07 上午11.47.41.png

  • webpack.config.js 里面对应的地方修改如下:

截屏2022-06-07 上午11.34.35.png

截屏2022-06-07 上午11.35.01.png

3.代码压缩打包

压缩css,引入插件 css-minimizer-webpack-plugin

yarn add css-minimizer-webpack-plugin -D
复制代码

webpack.config.js增加如下配置:

截屏2022-06-07 下午3.05.40.png

压缩js,webpack5默认会在生产环境压缩js,开发环境不会压缩,当然我们可以通过手动配置来实现一些其他的压缩,webpack5自带了terser-webpack-plugin插件,但是如果你想要自己配置压缩js的话,还是需要安装terser-webpack-plugin的。

yarn add terser-webpack-plugin -D
复制代码

webpack.dev.js 增加配置如下:

截屏2022-06-07 下午3.07.52.png

五、ts环境配置

1.安装ts 和 ts-loader

yarn add typescript ts-loader -D
复制代码

webpack.config.js增加配置如下: 截屏2022-06-07 下午6.24.01.png

2.增加tsconfig.json

tsconfig.json指定了编译项目所需的根目录下的文件以及编译选项。

{
  "compilerOptions": {
    "target": "es5",
    "lib": ["dom", "es5", "es6", "es7", "dom.iterable", "esnext"],
    "allowJs": true,
    "skipLibCheck": true,
    "esModuleInterop": true,
    "allowSyntheticDefaultImports": true,
    "strict": true,
    "forceConsistentCasingInFileNames": true,
    "noFallthroughCasesInSwitch": true,
    "module": "esnext",
    "moduleResolution": "node",
    "resolveJsonModule": true,
    "isolatedModules": true,
    "noEmit": false,
    "jsx": "react-jsx",
    "downlevelIteration": true
  },
  "include": ["src"]
}
复制代码

3.增加react的类型校验

yarn add @types/react @types/react-dom -D
复制代码

4.修改文件后缀

将原来的index.js 和 App.js 改为 index.tsx App.tsx,改名之后,index.tsx里面需要引入App,这时候会报错,此时可以将 import App from "./App.tsx"的后缀去掉,改为 import App from "./App",接着在webpack.config.js里面增加拓展名。

截屏2022-06-07 下午6.40.25.png webpack.config.js增加如下配置,extensions扩展名选项在resolve追踪到的文件如果没有扩展名时,会尝试在其提供的扩展名选项里进行匹配。 截屏2022-06-07 下午6.40.44.png

5.结果

经过上述配置,最后页面可以成功显示。至此,webpack+react+ts项目搭建成功。

猜你喜欢

转载自juejin.im/post/7106696029810098207