在本文中,我们将为您详细介绍从零配置webpack(react+less+typescript+mobx)的相关知识,并且为您解答关于从零配置gfpgan的疑问,此外,我们还会提供一些关于React+
在本文中,我们将为您详细介绍从零配置webpack(react+less+typescript+mobx)的相关知识,并且为您解答关于从零配置gfpgan的疑问,此外,我们还会提供一些关于React + Typescript + Webpack 开发环境配置、React+TypeScript+Mobx+AntDesignMobile进行移动端项目搭建、React+TypeScript+webpack4多入口配置、React+TypeScript+webpack4多入口配置详解的有用信息。
本文目录一览:- 从零配置webpack(react+less+typescript+mobx)(从零配置gfpgan)
- React + Typescript + Webpack 开发环境配置
- React+TypeScript+Mobx+AntDesignMobile进行移动端项目搭建
- React+TypeScript+webpack4多入口配置
- React+TypeScript+webpack4多入口配置详解
从零配置webpack(react+less+typescript+mobx)(从零配置gfpgan)
本文目标
从零搭建出一套支持react+less+typescript+mobx的webpack配置
最简化webpack配置
首页要初始化yarn和安装webpack的依赖
yarn init -y
yarn add webpack webpack-cli -D
根目录下新建webpack.config.js文件,内容如下
const path = require(''path'');
module.exports = {
mode: ''development'',
// 入口 这里应用程序开始执行
entry: path.resolve(__dirname, ''src/index.tsx''),
// 出口
output: {
// 输出文件的目标路径
path: path.resolve(__dirname, ''dist''),
// 输出的文件名
filename: ''bundle.js'',
// 输出解析文件的目录。静态资源最终访问路径 = output.publicPath + 资源loader或插件等配置路径
publicPath: ''/''
}
}
使用命令进行打包
webpack --mode production
另外亦可以将命令配置到 package.json 中的 scripts 字段
"scripts": {
"build": "webpack --mode production"
},
执行命令 yarn build 即可打包
使用模版html
html-webpack-plugin 插件 可以指定template模板文件,将会在output目录下,生成html文件,并引入打包后的js.
安装依赖
yarn add html-webpack-plugin -D
在webpack.config.js增加plugins配置
const HtmlWebpackPlugin = require(''html-webpack-plugin'');
module.exports = {
//...other code
plugins: [
new HtmlWebpackPlugin({
template: path.resolve(__dirname, ''src/index.html'')
})
]
}
html-webpack-plugin 插件 还支持title、minify、filename等其他参数
配置webpack-dev-server
webpack-dev-server提供了一个简单的Web服务器和实时热更新的能力,有助于开发。
安装依赖
yarn add webpack-dev-server -D
在webpack.config.js中增加devServer配置
const path = require(''path'');
const HtmlWebpackPlugin = require(''html-webpack-plugin'');
module.exports = {
//...other code
devServer: {
hot: true,
port: 3000,
open: true,
contentBase: path.resolve(__dirname, ''dist''),
// 开发模式下写/就行啦
publicPath: ''/'',
}
}
在 package.json 的 scripts 字段中增加 start模式
"scripts": {
"start": "webpack-dev-server --mode development",
"build": "webpack --mode production"
},
这样我们就可以通过yarn start来启动服务啦
官网devServer
链接Webpack中publicPath详解
支持加载css文件
通过使用不同的 style-loader 和 css-loader, 可以将 css 文件转换成js 文件类型。
安装依赖
yarn add style-loader css-loader -D
在webpack.config.js中增加loader配置
module.exports = {
//other code
module: {
rules: [
{
test: /\.css/,
use: [''style-loader'', ''css-loader''],
exclude: /node_modules/,
include: path.resolve(__dirname, ''src'')
}
]
}
}
loader 可以配置以下参数:
- test: 匹配处理文件的扩展名的正则表达式
- use: loader名称
- include/exclude: 手动指定必须处理的文件夹或屏蔽不需要处理的文件夹
- query: 为loader提供额外的设置选项
支持图片加载
需要引入两个loader
- file-loader: 解决CSS等文件中的引入图片路径问题
- url-loader: 当图片小于limit的时候会把图片Base64编码,大于limit参数的时候还是使用file-loader进行拷贝
如果希望图片存放在单独的目录下,那么需要指定outputPath
安装依赖
yarn add url-loader file-loader -D
在 webpack.config.js 中增加 loader 的配置(增加在 module.rules 的数组中)。
module.exports = {
//other code
module: {
rules: [
{
test: /\.(gif|jpg|png|bmp|eot|woff|woff2|ttf|svg)/,
use: [
{
loader: ''url-loader'',
options: {
limit: 8192,
outputPath: ''images''
}
}
]
}
]
}
}
支持编译less
很多前端都喜欢写less,所以支持less也是需要的。(sass配置方法基本相同)
安装依赖
yarn add less less-loader -D
在 webpack.config.js 中增加 loader 的配置(module.rules 数组中)。
module.exports = {
//other code
module: {
rules: [
{
test: /\.less/,
use: [''style-loader'', ''css-loader'', ''less-loader''],
exclude: /node_modules/,
include: path.resolve(__dirname, ''src'')
},
]
}
}
支持转义 ES6/ES7/JSX(react)
安装ES6/ES7/JSX 转义需要 Babel 的依赖,支持装饰器。
yarn add @babel/core babel-loader @babel/preset-env @babel/preset-react @babel/plugin-proposal-decorators @babel/plugin-proposal-object-rest-spread -D
在 webpack.config.js 中增加 loader 的配置(module.rules 数组中)。
module.exports = {
//other code
module: {
rules: [
{
test: /\.jsx?$/,
use: [
{
loader: ''babel-loader'',
options: {
presets: [''@babel/preset-env'', ''@babel/react''],
plugins: [
[
"@babel/plugin-proposal-decorators",
{ "legacy": true }
]
]
}
}
],
include: path.resolve(__dirname, ''src''),
exclude: /node_modules/
},
]
}
}
压缩JS文件
安装依赖
yarn add uglifyjs-webpack-plugin -D
在 webpack.config.js 中增加 optimization 的配置
const UglifyWebpackPlugin = require(''uglifyjs-webpack-plugin'');
module.exports = {
//other code
optimization: {
minimizer: [
new UglifyWebpackPlugin({
parallel: 4
})
]
}
}
分离出CSS
因为CSS的下载和JS可以并行,当一个HTML文件很大的时候,可以把CSS单独提取出来加载
安装依赖
yarn add mini-css-extract-plugin -D
在 webpack.config.js 中增加 plugins 的配置,并且将 ''style-loader'' 修改为 { loader: MiniCssExtractPlugin.loader}。CSS打包在单独目录,那么配置filename。
const MiniCssExtractPlugin = require(''mini-css-extract-plugin'');
module.exports = {
//other code
module: {
rules: [
{
test: /\.css/,
use: [{ loader: MiniCssExtractPlugin.loader}, ''css-loader''],
exclude: /node_modules/,
include: path.resolve(__dirname, ''src'')
},
{
test: /\.less/,
use: [{ loader: MiniCssExtractPlugin.loader }, ''css-loader'', ''less-loader''],
exclude: /node_modules/,
include: path.resolve(__dirname, ''src'')
},
]
},
plugins: [
new MiniCssExtractPlugin({
filename: ''css/[name].css''
})
]
}
压缩CSS文件
安装依赖
yarn add optimize-css-assets-webpack-plugin -D
在 webpack.config.js 中的 optimization 中增加配置
const OptimizeCssAssetsWebpackPlugin = require(''optimize-css-assets-webpack-plugin'');
module.exports = {
//other code
optimization: {
minimizer: [
new OptimizeCssAssetsWebpackPlugin()
]
}
}
支持react和mobx
安装react依赖
yarn add react react-dom
安装mobx依赖
yarn add mobx mobx-react
支持typescript
安装依赖
yarn add typescript awesome-typescript-loader -D
安装react的类型依赖(否则会有命名空间和.d.ts相关报错)
yarn add @types/react @types/react-dom
在 webpack.config.js 中增加 loader 的配置(module.rules 数组中)。
module.exports = {
//other code
module: {
rules: [
{
test: /\.(tsx|ts)?$/,
loader: "awesome-typescript-loader",
exclude: /node_modules/,
include: path.resolve(__dirname, ''src'')
}
]
}
}
在根目录下添加tsconfig.json
{
"compilerOptions": {
"baseUrl": ".",
"outDir": "build/dist",
"module": "esnext",
"target": "es5",
"lib": ["es6", "dom"],
"sourceMap": true,
"allowJs": true,
"jsx": "react",
"moduleResolution": "node",
"experimentalDecorators": true,
"rootDir": "./",
"forceConsistentCasingInFileNames": true,
"noImplicitReturns": true,
"noImplicitThis": true,
"noImplicitAny": false,
"importHelpers": true,
"strictNullChecks": true,
"suppressImplicitAnyIndexErrors": true,
"noUnusedLocals": false,
"allowSyntheticDefaultImports": true
},
"exclude": [
"node_modules",
"build",
"scripts",
"acceptance-tests",
"webpack",
"jest",
"src/setupTests.ts"
]
}
在根目录下添加tslint.json
{
"extends": ["tslint:recommended", "tslint-react", "tslint-config-prettier"],
"rules": {
"no-empty-interface":false,
"no-empty-block":false,
"no-unused-expression":false,
"object-literal-sort-keys":false,
"no-empty":false,
"semicolon": [false, "always"],
"no-default-export": false,
"member-access": true,
"ordered-imports": false,
"import-sources-order": "any",
"named-imports-order": "any",
"interface-over-type-literal":false,
"jsx-no-lambda":false,
"variable-name": [
true,
"ban-keywords",
"check-format",
"allow-leading-underscore",
"allow-trailing-underscore",
"allow-pascal-case",
"allow-snake-case"
],
"no-console": false,
"no-angle-bracket-type-assertion": false,
"jsx-no-string-ref":false,
"prefer-for-of":false,
"member-ordering":false,
"only-arrow-functions":false,
"object-literal-shorthand":false
},
"linterOptions": {
"exclude": [
"config/**/*.js",
"node_modules/**/*.ts",
"coverage/lcov-report/*.js"
]
},
"strict": false
}
打包前先清空输出目录
安装依赖
yarn add clean-webpack-plugin -D
在 webpack.config.js 中增加 plugins 的配置
const {CleanWebpackPlugin} = require(''clean-webpack-plugin'');
module.exports = {
//other code
plugins: [
new CleanWebpackPlugin()
]
}
( 注意3.0版本的clean-webpack-plugin有大改动,需要通过构造函数取出CleanWebpackPlugin再用 )
至此,webpack配置已经基本能满足react+less+typescript+mobx开发需求。
完整webpack.config.js和package.json文件
webpack.config.js文件
const path = require(''path'');
// 打包html的插件
const HtmlWebpackPlugin = require(''html-webpack-plugin'');
// 压缩JS的插件
const UglifyWebpackPlugin = require(''uglifyjs-webpack-plugin'');
// 分离css文件
const MiniCssExtractPlugin = require(''mini-css-extract-plugin'');
// 打包前先清空输出目录
const {CleanWebpackPlugin} = require(''clean-webpack-plugin'');
module.exports = {
mode: ''development'',
// 入口 这里应用程序开始执行
entry: path.resolve(__dirname, ''src/index.tsx''),
// 出口
output: {
// 所有输出文件的目标路径
path: path.resolve(__dirname, ''dist''),
// 输出的文件名
filename: ''bundle.js'',
// 输出解析文件的目录,url 相对于 HTML 页面, publicPath 上线时配置的是cdn的地址。
// 静态资源最终访问路径 = output.publicPath + 资源loader或插件等配置路径
publicPath: ''./''
},
devServer: {
hot: true,
port: 3000,
open: true,
contentBase: path.resolve(__dirname, ''dist''),
publicPath: ''/'',
// stats: ''none''
},
module: {
rules: [
/*
* 支持css
* 通过使用不同的 style-loader 和 css-loader, 可以将 css 文件转换成JS文件类型。
* */
{
test: /\.css/,
// use: [''style-loader'', ''css-loader''],
use: [
{
loader: MiniCssExtractPlugin.loader
},
''css-loader''
],
exclude: /node_modules/,
include: path.resolve(__dirname, ''src'')
},
/*
* 支持编译less和sass
* */
{
test: /.less/,
// use: [''style-loader'', ''css-loader'', ''less-loader''],
use: [
{
loader: MiniCssExtractPlugin.loader
},
''css-loader'',
''less-loader''
],
exclude: /node_modules/,
include: path.resolve(__dirname, ''src'')
},
/*
* 支持加载图片
* file-loader: 解决CSS等文件中的引入图片路径问题
* url-loader: 当图片小于limit的时候会把图片Base64编码,大于limit参数的时候还是使用file-loader进行拷贝
* */
{
test: /\.(gif|jpg|png|bmp|eot|woff|woff2|ttf|svg)/,
use: [
{
loader: ''url-loader'',
options: {
limit: 1,
outputPath: ''images''
}
}
]
},
/*
* 支持转义 ES6/ES7/JSX ,支持react
* ES6/ES7/JSX 转义需要 Babel 的依赖,支持装饰器。
* */
{
test: /\.jsx?$/,
use: [
{
loader: "babel-loader",
options: {
presets: [''@babel/preset-env'', ''@babel/react''],
plugins: [
[
"@babel/plugin-proposal-decorators",
// "@babel/plugin-proposal-class-properties",
{
"legacy": true
}
]
]
}
}
],
exclude: /node_modules/,
include: path.resolve(__dirname, ''src'')
},
/*
* 支持转义 支持typescript
* ES6/ES7/JSX 转义需要 Babel 的依赖,支持装饰器。
* */
{
test: /\.(tsx|ts)?$/,
loader: "awesome-typescript-loader",
exclude: /node_modules/,
include: path.resolve(__dirname, ''src'')
}
]
},
optimization: {
minimizer: [
new UglifyWebpackPlugin({
parallel: 4
})
]
},
plugins: [
new HtmlWebpackPlugin({
template: path.resolve(__dirname, ''public/index.html'')
}),
new MiniCssExtractPlugin({
filename:''css/[name].css''
}),
new CleanWebpackPlugin()
]
};
package.json文件
{
"name": "webpack_cli",
"version": "1.0.0",
"main": "index.js",
"license": "MIT",
"scripts": {
"start": "webpack-dev-server --mode development",
"build": "webpack --mode production"
},
"devDependencies": {
"@babel/core": "^7.5.5",
"@babel/plugin-proposal-decorators": "^7.4.4",
"@babel/plugin-proposal-object-rest-spread": "^7.5.5",
"@babel/preset-env": "^7.5.5",
"@babel/preset-react": "^7.0.0",
"@types/react": "^16.9.2",
"@types/react-dom": "^16.8.5",
"awesome-typescript-loader": "^5.2.1",
"babel-loader": "^8.0.6",
"clean-webpack-plugin": "^3.0.0",
"css-loader": "^3.2.0",
"file-loader": "^4.2.0",
"html-webpack-plugin": "^3.2.0",
"less": "^3.10.1",
"less-loader": "^5.0.0",
"mini-css-extract-plugin": "^0.8.0",
"optimize-css-assets-webpack-plugin": "^5.0.3",
"style-loader": "^1.0.0",
"typescript": "^3.5.3",
"uglifyjs-webpack-plugin": "^2.2.0",
"url-loader": "^2.1.0",
"webpack": "^4.39.2",
"webpack-cli": "^3.3.7",
"webpack-dev-server": "^3.8.0"
},
"dependencies": {
"mobx": "^5.13.0",
"mobx-react": "^6.1.3",
"react": "^16.9.0",
"react-dom": "^16.9.0"
}
}
学习更多webpack配置请进入webpack官网 webpack官网链接
本文配置将持续升级优化
React + Typescript + Webpack 开发环境配置
对于复杂或多人开发的 React
项目来说,管理和使用每个组件的 props
、 state
或许会成为一件让人头痛的事情,而为每一个组件写文档,成本也会比较大,对项目的开发效率也不是最理想的。
Typescript
给 React
带来很多好处:
- 在组件头部定义
interface
,让每个人在拿到组件的第一时间就可以很明确知道该组件需要使用的props
和state
; - 在编译中发现问题,减少运行时的报错;
- 可以在编辑器中实现实时类型校验、引用查询;
- 约束类型,在混合多语言环境中降低风险,等。
且配置也是非常简单,步骤如下。
文件目录
. ├── build # 前端配置文件 │ ├── index.html │ ├── webpack.config.js ├── app # 前端目录 ├── .gitignore ├── package.json ├── tsconfig.json └── tslint.json
配置流程
创建项目
mkdir my-project && cd my-project npm init
安装依赖
npm i -g webpack webpack-dev-server npm i --save react react-dom @types/react @types/react-dom npm i --save-dev ts-loader source-map-loader npm link webpack webpack-dev-server typescript
配置 webpack
/* build/webpack.config.js */ const config = { entry: './app/index.tsx', output: { filename: 'app.bundle.js', path: './public', publicPath: '/assets' }, devtool: 'source-map', resolve: { extensions: ['', '.webpack.js', '.web.js', '.ts', '.tsx', '.js'] }, module: { loaders: [ { test: /\.tsx?$/, loader: 'ts-loader' } ], preLoaders: [ { test: /\.js$/, loader: 'source-map-loader' } ] }, devtool: 'eval' } module.exports = config
配置 tsconfig
/* tsconfig.json */ { "compilerOptions": { "outDir": "./public/", "sourceMap": true, "noImplicitAny": true, "module": "commonjs", "target": "es5", "jsx": "react" }, "files": [ "./app/index.tsx" ] }
至此,基本配置已经完成,后面创建好一个入口页面和entry
文件就可以跑起来了:
<!-- build/index.html --> <!doctype html> <html lang="zh-cn"> <head> <Meta charset="utf-8"> <Meta name="viewport" content="width=device-width,initial-scale=1.0,user-scalable=no"> <title>Hello world</title> <script src="http://localhost:8080/webpack-dev-server.js"></script> </head> <body> <div id="app"></div> <script src="assets/app.bundle.js"></script> </body>
/* app/index.tsx */ import * as React from 'react' import { render } from 'react-dom' interface IAppProps {} interface IAppState {} class App extends React.Component<IAppProps, IAppState> { public render(): JSX.Element { return ( <div> Hello world </div> ) } } render(<App />, document.getElementById('app'))
启动项目
webpack-dev-server --inline --config build/webpack.config.js --content-base build --open
:smirk: :smirk: :smirk: 出来吧神龙
简单的说明
Webpack 配置
Webpack配置其实是一件很简单的事情,这也是他具备强大竞争力的重要因素。
从配置文件中可以看出,里面无非就是entry
、output
和loader
,如果需要编译CSS,在loader
里面加一个即可:
npm i --save-dev style-loader css-loader
/* build/webpack.config.js */ const config = { // ... module: { loaders: [ { test: /\.css/, loader: 'style-loader!css-loader' } ], // ... }, // ... }
项目启动
项目启动的命令过长,放进 package.json
的 scripts
就好了:
/* package.json */ { "scripts": { "dev": "webpack-dev-server --inline --config build/webpack.config.js --content-base build --open", }, }
再执行以下命令试试:
npm run dev
tslint
在开发中如果有个约束代码的工具能够让代码更加优雅,以前用的是 eslint
,如果用 .tsx
就不能生效了,这里推荐使用 tslint
:
npm i -g tslint cd my-project tslint --init
这样会在项目文件中创建一个现成的 tslint
配置文件: tslint.json
,个性化方案可以自行设置。
React+TypeScript+Mobx+AntDesignMobile进行移动端项目搭建
前言:
本文基于React+TypeScript+Mobx+AntDesignMobile技术栈,使用Create-React-App脚手架进行一个移动端项目搭建,主要介绍项目搭建过程和相关配置,以及状态管理工具Mobx的使用,最后实现点击按钮数字+1和一个简单的TodoList小功能,希望能对大家有所帮助。GitHub代码地址
项目搭建具体步骤:
- 安装Create-React-App脚手架工具,已经安装的同学请忽略
npm install create-react-app -g
- 创建初始项目
create-react-app my-app --typescript
注意:
如果同学你是参考typescript官方文档进行react项目搭建,里面有用create-react-app my-app --scripts-version=react-scripts-ts
命令创建的,千万别用,现在已经过时了,
webpack版本有问题,后续配置各种想不到的坑 TypeScript中文官网 -
引入AntDesignMobile,实现组件按需加载
本步骤官网有比较详细的介绍,我就不一一列举配置过程了,建议大家不要eject暴露所有内建配置,后续版本升级维护可能比较麻烦,推荐使用 react-app-rewired 插件即可配置;AntDesignMobile官网
-
安装React路由,状态管理工具mobx,配置sass
npm install history @types/history react-router-dom @types/react-router-dom // 安装react路由 npm install mobx-react mobx // 安装mobx npm install node-sass // 安装sass工具,安装之后无需另外配置sass,脚手架工具已经集成了
- 基本配置完成,运行项目
npm run start
React状态管理工具Mobx介绍:
Mobx是一个功能强大,基于面向对象编程方式的一个状态管理工具,上手相对比较容易。就连Redux的作者也曾经向大家推荐过它,对TypeScript支持比较友好,参考官网一张流程图:
Mobx中文官网
下面介绍几个Mobx核心概念
Observable state(可观察的状态)
MobX 为现有的数据结构(如对象,数组和类实例)添加了可观察的功能。 通过使用 @observable 装饰器(ES.Next)来给你的类属性添加注解就可以简单地完成这一切。
import { observable } from "mobx";
class Todo {
id = Math.random();
@observable title = "";
@observable finished = false;
}
Computed values(计算值)
使用 MobX, 你可以定义在相关数据发生变化时自动更新的值。 通过@computed 装饰器或者利用 (extend)Observable 时调用 的getter / setter 函数来进行使用,下面代码中当queue或者refresh发生变化时,MobX会监听数据变化确保,通过Computed触发fooProps方法自动更新。
import React from ''react'';
import {observable, isArrayLike, computed, action, autorun, when, reaction,runInAction} from "mobx";
import {observer} from ''mobx-react'';
// 定义数据Store
class Store {
@observable queue:number = 1;
@action refresh = ():void => {
this.queue += 1;
console.log(''this.queue -> '', this.queue);
}
@computed get fooProps():any {
return {
queue: this.queue,
refresh: this.refresh
};
}
}
Actions(动作)
任何应用都有动作。动作是任何用来修改状态的东西,mobx推荐将修改被观测变量的行为放在action中。action只能影响正在运行的函数,而无法影响当前函数调用的异步操作,参考官方文档用法:
action(fn)
action(name, fn)
@action classMethod() {}
@action(name) classMethod () {}
@action boundClassMethod = (args) => { body }
@action(name) boundClassMethod = (args) => { body }
@action.bound classMethod() {}
action 装饰器/函数遵循 javascript 中标准的绑定规则。 但是,action.bound 可以用来自动地将动作绑定到目标对象。 注意,与 action 不同的是,(@)action.bound 不需要一个name参数,名称将始终基于动作绑定的属性。
class Ticker {
@observable tick = 0
@action.bound
increment() {
this.tick++ // ''this'' 永远都是正确的
}
}
const ticker = new Ticker()
setInterval(ticker.increment, 1000)
利用Mobx作为状态管理,实现两个小功能
点击按钮+1
import React from ''react'';
import {observable, isArrayLike, computed, action, autorun, when, reaction,runInAction} from "mobx";
import {observer} from ''mobx-react'';
import {Button} from ''antd-mobile'';
import ''./index.scss'';
// 定义数据Store,用Mobx作为状态管理工具
class Store {
@observable queue:number = 1;
@action refresh = ():void => {
this.queue += 1;
console.log(''this.queue -> '', this.queue);
}
@computed get fooProps():any {
return {
queue: this.queue,
refresh: this.refresh
};
}
}
// ts组件接收父组件传递过来的数据必须定义接口类型,否则报错
interface BarProps{
queue :number
}
// @observer修饰类,Bar组件接受Foo组建传过来的queue属性
@observer
class Bar extends React.Component<BarProps>{
render() {
const {queue} = this.props
return (
<div className="queue">{queue}</div>
)
}
}
interface FooProps {
queue: number,
refresh():void
}
// Foo组件接收来自Add组件的store数据
@observer
class Foo extends React.Component<FooProps>{
render() {
const {queue,refresh} = this.props;
return (
<div>
<Button type="primary" onClick = {refresh}>Refresh</Button>
<Bar queue = {queue} />
</div>
)
}
}
// 初始化store数据,传递给Foo组件
const store = new Store();
class Add extends React.Component{
render() {
return (
<div>
<h2 className="add"> hello react-ts-mobx</h2>
<Foo queue = {store.queue} refresh = {store.refresh} />
</div>
)
}
}
export default observer(Add)
TodoList功能
import React from ''react'';
import {observable, isArrayLike, computed, action, autorun, when, reaction,runInAction} from "mobx";
import {observer} from ''mobx-react'';
import ''./index.scss'';
// 定义Todo数据类型
class Todo {
id:number = new Date().getTime();
title:string = '''';
finished:boolean = false;
constructor(title:string) {
this.title = title;
}
}
// Store数据方法管理
class Store {
@observable title:string = '''';
@observable todos:Todo[] =[];
// 添加Todo的Title
@action createTitle (e:any) {
console.log(''e'',e.target.value);
this.title = e.target.value;
}
// 增加Todo数据
@action createTodo = () => {
this.todos.unshift(new Todo(this.title));
this.title = '''';
}
// 删除Todo
@action delTodo (id:number) {
this.todos.forEach((item,index) => {
if (item.id === id) {
this.todos.splice(index,1)
}
})
}
// 监听todos数据变化,显示剩余待办数量
@computed get unfinished () {
return this.todos.filter(todo => !todo.finished).length;
}
}
interface TodoItemProps {
todo:any;
store:any;
}
// 每一条Todo数据组件
@observer
class TodoItem extends React.Component<TodoItemProps> {
render() {
const {todo,store} = this.props
return (
<div className="item">
<span>{todo.title}</span>
<span onClick={()=> store.delTodo(todo.id)}>X</span>
</div>
)
}
}
const store = new Store();
@observer
class TodoList extends React.Component {
render() {
return (
<div>
<h2>TodoList</h2>
<header>
<input type="text" placeholder="please input" value={store.title} onChange = {e => store.createTitle(e)} />
<button onClick ={store.createTodo}>add</button>
</header>
<ul>
{store.todos.map((todo)=>{
return <li key={todo.id}>
<TodoItem todo={todo} store = {store}/>
</li>
})}
</ul>
<footer>
{store.unfinished} item(s) unfinished
</footer>
</div>
)
}
}
export default TodoList
总结:
本人刚接触TypeScript和Mobx不久,总结学习方法:应该先熟悉一些基本概念后,慢慢的做一些小功能,遇到问题认真思考后再查资料或者请教别人,反复看文档,加强对知识的理解;欢迎大佬们留言交流;GitHub代码地址
React+TypeScript+webpack4多入口配置
资源
- 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
项目来说,管理和使用每个组件的 props
、 state
或许会成为一件让人头痛的事情,而为每一个组件写文档,成本也会比较大,对项目的开发效率也不是最理想的。
Typescript
给 React
带来很多好处:
- 在组件头部定义
interface
,让每个人在拿到组件的第一时间就可以很明确知道该组件需要使用的props
和state
; - 在编译中发现问题,减少运行时的报错;
- 可以在编辑器中实现实时类型校验、引用查询;
- 约束类型,在混合多语言环境中降低风险,等。
需求
要搭建一个React+TypeScript+webpack的项目的话,一般都是团队开发多人多文件项目,在搭建之前需要优先考虑以下几个方面:
- 开发体验
- 项目打包
- 团队规范
安装
-
前置安装
首先需要全局安装typescript,这里默认大家都已经安装了node以及npmnpm install -g typescript
-
首先新建文件夹并进入
mkdir tsDemo && cd tsDemo
-
然后进行初始化,生成
package.json
和tsconfig.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
-
entry
:入口文件(你要打包,就告诉我打包哪些) -
output
:出口文件(我打包完了,给你放到哪里) -
resolve
: 寻找模块所对应的文件 -
module
:模块(放lorder,编译浏览器不认识的东西) -
plugins
:插件(辅助开发,提高开发效率) -
externals
:打包忽略 -
devServer
:服务器(webpack提供的本地服务器) -
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
文件都是一个模块,都能用导入模块的语法(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
就是一个用来处理不同文件的规则
所需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 处理csssass-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
mode
是webpack4
新增的一条属性,它的意思为当前开发的环境。mode
的到来减少了很多的配置,它内置了很多的功能。相较以前的版本提升了很多,减少了很多专门的配置
- 提升了构建速度
- 默认为开发环境,不需要专门配置
- 提供压缩功能,不需要借助插件
- 提供
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 // 自动打开首页
}
}
React+TypeScript+webpack4多入口配置详解
资源
- 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 项目来说,管理和使用每个组件的 props 、 state 或许会成为一件让人头痛的事情,而为每一个组件写文档,成本也会比较大,对项目的开发效率也不是最理想的。
Typescript 给 React 带来很多好处:
- 在组件头部定义 interface,让每个人在拿到组件的第一时间就可以很明确知道该组件需要使用的 props 和 state;
- 在编译中发现问题,减少运行时的报错;
- 可以在编辑器中实现实时类型校验、引用查询;
- 约束类型,在混合多语言环境中降低风险,等。
需求
要搭建一个React+TypeScript+webpack的项目的话,一般都是团队开发多人多文件项目,在搭建之前需要优先考虑以下几个方面:
- 开发体验
- 项目打包
- 团队规范
安装
前置安装
首先需要全局安装typescript,这里默认大家都已经安装了node以及npm
npm install -g typescript
首先新建文件夹并进入
mkdir tsDemo && cd tsDemo
然后进行初始化,生成package.json和tsconfig.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
- entry:入口文件(你要打包,就告诉我打包哪些)
- output:出口文件(我打包完了,给你放到哪里)
- resolve: 寻找模块所对应的文件
- module:模块(放lorder,编译浏览器不认识的东西)
- plugins:插件(辅助开发,提高开发效率)
- externals:打包忽略
- devServer:服务器(webpack提供的本地服务器)
- 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文件都是一个模块,都能用导入模块的语法(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就是一个用来处理不同文件的规则
所需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
mode是webpack4新增的一条属性,它的意思为当前开发的环境。mode的到来减少了很多的配置,它内置了很多的功能。相较以前的版本提升了很多,减少了很多专门的配置
- 提升了构建速度
- 默认为开发环境,不需要专门配置
- 提供压缩功能,不需要借助插件
- 提供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 // 自动打开首页 } }
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。
- React+Webpack快速上手指南(小结)
- 从零搭建Webpack5-react脚手架的实现步骤(附源码)
- 使用webpack配置react-hot-loader热加载局部更新
今天的关于从零配置webpack(react+less+typescript+mobx)和从零配置gfpgan的分享已经结束,谢谢您的关注,如果想了解更多关于React + Typescript + Webpack 开发环境配置、React+TypeScript+Mobx+AntDesignMobile进行移动端项目搭建、React+TypeScript+webpack4多入口配置、React+TypeScript+webpack4多入口配置详解的相关知识,请在本站进行查询。
本文标签: