├── 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
项目来讲,管理和使用每一个组件的 props
、 state
或许会成为一件让人头痛的事情,而为每个组件写文档,成本也会比较大,对项目的开发效率也不是最理想的。css
Typescript
给 React
带来不少好处:html
interface
,让每一个人在拿到组件的第一时间就能够很明确知道该组件须要使用的 props
和 state
;要搭建一个React+TypeScript+webpack的项目的话,通常都是团队开发多人多文件项目,在搭建以前须要优先考虑如下几个方面:node
前置安装
首先须要全局安装typescript,这里默认你们都已经安装了node以及npmreact
npm install -g typescript
首先新建文件夹并进入webpack
mkdir tsDemo && cd tsDemo
而后进行初始化,生成package.json
和tsconfig.json
git
npm init -y && tsc --init
安装开发工具web
npm install-D webpack webpack-cli webpack-dev-server
安装react相关
由于须要整合ts,而react本来的包是不包含验证包的,因此这里也须要安装相关ts验证包typescript
npm install -S react react-dom npm install -D @types/react @types/react-dom
安装ts-loader
npm
npm install -D ts-loader
根目录下新建webpack.config.base.js、webpack.config.build.js、webpack.config.js文件json
touch webpack.config.base.js webpack.config.build.js webpack.config.js
entry
:入口文件(你要打包,就告诉我打包哪些)output
:出口文件(我打包完了,给你放到哪里)resolve
: 寻找模块所对应的文件module
:模块(放lorder,编译浏览器不认识的东西)plugins
:插件(辅助开发,提升开发效率)externals
:打包忽略devServer
:服务器(webpack提供的本地服务器)mode
:模式,分为开发模式、生产模式。此为4.X里新增的由于大部分项目是多入口,多类别的,全部入口配置时不要配置单一入口
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 };
const webpackConfig = { output: { //输出文件名称以当前传入的cate类别名称命名 filename: "[name].js", //输出到根目录下的dist目录中 path: path.resolve(__dirname, "dist"), publicPath: "/", }, }
须要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")] }, }
在webpack
中任何一个东西都称为模块,js
就不用说了。一个css
文件,一张图片、一个less
文件都是一个模块,都能用导入模块的语法(commonjs
的require
,ES6
的import
)导入进来。webpack
自身只能读懂js
类型的文件,其它的都不认识。可是webpack
却能编译打包其它类型的文件,像ES6
、JSX
、less
、typeScript
等,甚至css
、images
也是Ok的,而想要编译打包这些文件就须要借助loader
loader
就像是一个翻译员,浏览器不是不认识这些东西么?那好交给loader
来办,它能把这些东西都翻译成浏览器认识的语言。loader
描述了webpack
如何处理非js
模块,而这些模块想要打包loader
必不可少,因此它在webpack
里显得异常重要。loader
跟插件同样都是模块,想要用它须要先安装它,使用的时候把它放在module.rules
参数里,rules
翻译过来的意思就是规则,因此也能够认为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
sass-loader 编译处理scss
sass-resources-loader 全局注册变量
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
里面放的是插件,插件的做用在于提升开发效率,可以解放双手,让咱们去作更多有意义的事情。一些很low的事就通通交给插件去完成。
const webpackConfig = { plugins: [ //清除文件 new CleanWebpackPlugin(), //css单独打包 new MiniCssExtractPlugin({ filename: "[name].css", chunkFilename: "[name].css" }), // 引入热更新插件 new webpack.HotModuleReplacementPlugin() ] }
若是须要引用一个库,可是又不想让webpack打包(减小打包的时间),而且又不影响咱们在程序中以CMD、AMD或者window/global全局等方式进行使用(通常都以import方式引用使用),那就能够经过配置externals。
const webpackConfig = { //项目编译打包是忽略这些依赖包 externals: { react: "React", "react-dom": "ReactDOM", "react-redux": "ReactRedux", } }
mode
是webpack4
新增的一条属性,它的意思为当前开发的环境。mode
的到来减小了不少的配置,它内置了不少的功能。相较之前的版本提高了不少,减小了不少专门的配置
- 提高了构建速度
- 默认为开发环境,不须要专门配置
- 提供压缩功能,不须要借助插件
- 提供
SouceMap
,不须要专门配置
mode
分为两种环境,一种是开发环境(development
),一种是生产环境(production
)。开发环境就是咱们写代码的环境,生产环境就是代码放到线上的环境。这两种环境的最直观区别就是,开发环境的代码不提供压缩,生产环境的代码提供压缩。
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 // 自动打开首页 } }