ReactTypeScriptwebpack4多入口配置

22次阅读

共计 5768 个字符,预计需要花费 15 分钟才能阅读完成。

资源

  • React-16.8.*
  • react-router-dom-4.3.*
  • TypeScript-3.5.*
  • webpack-4.*
  • eslint-5.16.*

项目目录

├── dist # 打包结果目录
│   ├── demo1 // 类别 demo1 的打包结果
│    │    ├── demo1.himl
│   │    ├── demo1.js
│    │    └── demo1.css
│   └── demo2 ... // 类别 demo2 的打包结果
├── src # 业务资源文件目录
│    ├── category // 项目分类
│    │    ├── demo1
│    │    ├── demo2
│    │    └── ...
│    ├── components // 公共组件
│    ├── util // 公共资源
│    └── custom.d.ts // 项目全局变量声明文件
├── index.html // 项目启动入口
├── .gitignore //git 忽略文件
├── .eslintrc.js //eslint 校验配置
├── package.json // 依赖包
├── tsconfig.json //ts 配置
├── webpack.config.build.js //webpack 打包
├── webpack.config.base.js //webpack 基础配置
└── webpack.config.js // 项目启动配置

前言

对于复杂或多人开发的 React 项目来说,管理和使用每个组件的 propsstate 或许会成为一件让人头痛的事情,而为每一个组件写文档,成本也会比较大,对项目的开发效率也不是最理想的。

TypescriptReact 带来很多好处:

  • 在组件头部定义 interface,让每个人在拿到组件的第一时间就可以很明确知道该组件需要使用的 propsstate
  • 在编译中发现问题,减少运行时的报错;
  • 可以在编辑器中实现实时类型校验、引用查询;
  • 约束类型,在混合多语言环境中降低风险,等。

需求

要搭建一个 React+TypeScript+webpack 的项目的话,一般都是团队开发多人多文件项目,在搭建之前需要优先考虑以下几个方面:

  • 开发体验
  • 项目打包
  • 团队规范

安装

  • 前置安装
    首先需要全局安装 typescript,这里默认大家都已经安装了 node 以及 npm

    npm install -g typescript
  • 首先新建文件夹并进入

    mkdir tsDemo && cd tsDemo
  • 然后进行初始化,生成 package.jsontsconfig.json

    npm init -y && tsc --init
  • 安装开发工具

    npm install-D webpack webpack-cli webpack-dev-server
  • 安装 react 相关
    因为需要整合 ts,而 react 原本的包是不包含验证包的,所以这里也需要安装相关 ts 验证包

    npm install -S react react-dom
    npm install -D @types/react @types/react-dom
  • 安装ts-loader

    npm install -D ts-loader
  • 以上是基本的 后续会贴出项目 demo 里面包含所有依赖包

webpack 配置

添加 webpack 文件

根目录下新建 webpack.config.base.js、webpack.config.build.js、webpack.config.js 文件

touch webpack.config.base.js webpack.config.build.js webpack.config.js
  1. entry:入口文件(你要打包,就告诉我打包哪些)
  2. output:出口文件(我打包完了,给你放到哪里)
  3. resolve: 寻找模块所对应的文件
  4. module:模块(放 lorder,编译浏览器不认识的东西)
  5. plugins:插件(辅助开发,提高开发效率)
  6. externals: 打包忽略
  7. devServer:服务器(webpack 提供的本地服务器)
  8. mode:模式,分为开发模式、生产模式。此为 4.X 里新增的

配置 entry 入口文件

因为大部分项目是多入口,多类别的,所有入口配置时不要配置单一入口

const fs = require("fs");
const path = require("path");
const optimist = require("optimist");

const cateName = optimist.argv.cate;
let entryObj = {};
const srcPath = `${__dirname}/src`;
// 获取当前项目要启动或者打包的基础路径
const entryPath = `${srcPath}/category/`;
// 未指定类别 启动或者打包所有类别
// 如:npm run dev 或者 npm run build
if (cateName == true) {fs.readdirSync(entryPath).forEach((cateName, index) => {
        // cateName/cateName 指定输出路径为 entryname
        if (cateName != "index.html" && cateName != ".DS_Store") entryObj[`${cateName}/${cateName}`] = `${entryPath + cateName}/${cateName}.tsx`;
    });
} else if (cateName.indexOf(",")) {
    // 一次指定多个类别 类别之间以 "," 分割
    // 如:npm run dev erhsouche,huoche 
    let cateNameArray = cateName.split(",");
    for (let i = 0; i < cateNameArray.length; i++) {entryObj[`${cateNameArray[i]}/${cateNameArray[i]}`] = `${entryPath + cateNameArray[i]}/${cateNameArray[i]
        }.tsx`;
    }
} else {
    // 打包单个入口文件
    // 如:npm run dev ershouche
    entryObj[`${cateName}/${cateName}`] = `${entryPath + cateName}/${cateName}.tsx`;
}
const webpackConfig = {entry: entryObj,}
module.exports = {
    webpackConfig,
    entryObj
};

配置 output 出口文件

const webpackConfig = {
    output: {
        // 输出文件名称以当前传入的 cate 类别名称命名
        filename: "[name].js", 
        // 输出到根目录下的 dist 目录中
        path: path.resolve(__dirname, "dist"),
        publicPath: "/",
    },
}

配置 resolve

需要 import xxx from 'xxx' 这样的文件的话需要在 webpack 中的 resolve 项中配置extensions,这样以后引入文件就不需要带扩展名

const webpackConfig = {
    resolve: {extensions: [".tsx", ".ts", ".js", ".jsx", ".json"],
        // 配置项通过别名来把原导入路径映射成一个新的导入路径。alias: {images: path.join(__dirname, "src/util/img")
        },
        // 使用绝对路径指明第三方模块存放的位置,以减少搜索步骤
        modules: [path.resolve(__dirname, "node_modules")] 
    },
}

配置 module

概念

webpack 中任何一个东西都称为模块,js就不用说了。一个 css 文件,一张图片、一个 less 文件都是一个模块,都能用导入模块的语法(commonjsrequireES6import)导入进来。webpack自身只能读懂 js 类型的文件,其它的都不认识。但是 webpack 却能编译打包其它类型的文件,像 ES6JSXlesstypeScript 等,甚至 cssimages 也是 Ok 的,而想要编译打包这些文件就需要借助loader

loader就像是一个翻译员,浏览器不是不认识这些东西么? 那好交给 loader 来办,它能把这些东西都翻译成浏览器认识的语言。loader描述了 webpack 如何处理非 js 模块,而这些模块想要打包 loader 必不可少,所以它在 webpack 里显得异常重要。loader跟插件一样都是模块,想要用它需要先安装它,使用的时候把它放在 module.rules 参数里,rules翻译过来的意思就是规则,所以也可以认为 loader 就是一个用来处理不同文件的规则

所需 loader

  • ts-loader

    编译 TypeScript 文件

    npm install ts-loader -D
  • url-loader

    处理 css 中的图片资源时,我们常用的两种 loader 是 file-loader 或者 url-loader,两者的主要差异在于。url-loader 可以设置图片大小限制,当图片超过限制时,其表现行为等同于 file-loader,而当图片不超过限制时,则会将图片以 base64 的形式打包进 css 文件,以减少请求次数。

    npm install url-loader -D
  • css 处理所需 loader
    css-loader 处理 css

    sass-loader 编译处理 scss

    sass-resources-loader 全局注册变量

  • html-loader
    处理.html 文件

module 完整配置

const webpackConfig = {
    module: {
        rules: [
            // 处理 tsx 文件
            {test: /\.(tsx|ts)?$/, use: ["ts-loader"], include: path.resolve(__dirname, "src") },
            // 处理图片资源
            {test: /\.(png|jpe?g|jpg|gif|woff|eot|ttf|svg)/,
                use: [
                    // 对非文本文件采用 file-loader 加载
                    {
                        loader: "url-loader",
                        options: {
                            limit: 1024 * 30, // 30KB 以下的文件
                            name: "images/[name].[hash:8].[ext]",
                        }
                    }
                ],
            },
            // 处理 css 和 scss
            {test: /\.(css|scss)$/,
                use: [
                    //css 单独打包
                    MiniCssExtractPlugin.loader,
                    {loader: "css-loader"},
                    {
                        loader: "postcss-loader",
                        options: {plugins: () => [require("autoprefixer")],
                            sourceMap: true
                        }
                    },
                    {
                        loader: "sass-loader",
                        options: {sourceMap: true}
                    },
                    {
                        loader: "sass-resources-loader",
                        options: {resources: ["./skin/mixin.scss", "./skin/base.scss"]
                        }
                    }
                ],
                exclude: path.resolve(__dirname, "node_modules")
            },
            {
                test: /\.html$/,
                use: {loader: "html-loader",}
            },
            {test: /src\/containers(\/.*).(tsx|ts)/, loader: "bundle-loader?lazy!ts-loader" },
            {enforce: "pre", test: /\.js$/, loader: "source-map-loader"}
        ]
    },
}

配置 plugins

plugins里面放的是插件,插件的作用在于提高开发效率,能够解放双手,让我们去做更多有意义的事情。一些很 low 的事就统统交给插件去完成。

const webpackConfig = {
    plugins: [
        // 清除文件
        new CleanWebpackPlugin(),
        //css 单独打包
        new MiniCssExtractPlugin({filename: "[name].css",
            chunkFilename: "[name].css"
        }),
        // 引入热更新插件
        new webpack.HotModuleReplacementPlugin()]
}

配置 externals

如果需要引用一个库,但是又不想让 webpack 打包(减少打包的时间),并且又不影响我们在程序中以 CMD、AMD 或者 window/global 全局等方式进行使用(一般都以 import 方式引用使用),那就可以通过配置 externals。

const webpackConfig = {
    // 项目编译打包是忽略这些依赖包
    externals: {
        react: "React",
        "react-dom": "ReactDOM",
        "react-redux": "ReactRedux",
    }
}

配置 mode

modewebpack4 新增的一条属性,它的意思为当前开发的环境。mode的到来减少了很多的配置,它内置了很多的功能。相较以前的版本提升了很多,减少了很多专门的配置

  1. 提升了构建速度
  2. 默认为开发环境,不需要专门配置
  3. 提供压缩功能,不需要借助插件
  4. 提供SouceMap,不需要专门配置

mode分为两种环境,一种是开发环境(development), 一种是生产环境(production)。开发环境就是我们写代码的环境,生产环境就是代码放到线上的环境。这两种环境的最直观区别就是,开发环境的代码不提供压缩,生产环境的代码提供压缩。

配置 devServer

const webpackConfig = {
    devServer: {
        // 本地服务器所加载的页面所在的目录
        contentBase: srcPath, 
        // 热更新
        hot: true,
        // 服务端口
        port: "7788",
        // 是否向 Chunk 中注入代理客户端,默认注入
        inline: true, 
        // publicPath: '/dist/',
        historyApiFallback: {index: "template.html",},
        // 默认检查 hostname
        disableHostCheck: true,
        compress: true,
        open: true // 自动打开首页
    }
}

正文完
 0