react項目,typescript + react 項目開發體驗之起手式

 2023-11-01 阅读 16 评论 0

摘要:目錄 起手式typescriptreact一些小姿勢react的狀態管理前言 typescript(以下簡稱ts) 官推是腳手架 create-react-app 的ts版本,可自行查閱。但是我沒有用它,原因有2: Webpack 版本是3.x,在組內用過4.x重構腳手架之后之后不想再回頭配3.x。

目錄

  • 起手式
  • typescript
  • react一些小姿勢
  • react的狀態管理

前言

typescript(以下簡稱ts) 官推是腳手架 create-react-app 的ts版本,可自行查閱。但是我沒有用它,原因有2:

  1. Webpack 版本是3.x,在組內用過4.x重構腳手架之后之后不想再回頭配3.x。
  2. 作為學習項目以及教程,方便貫穿整個項目構建流程。

react項目?接下來將分別從一些用到的tsconfig、webpack配置展開來講解

ts配置

編譯器安裝

ts 作為 js 的方言要編譯成 js 需要編譯器安裝(相關參考5分鐘上手TypeScript)

npm install -g typescript
復制代碼

react練手項目、編譯代碼當然也就是:

tsc 文件名.ts
復制代碼

最終默認會在當前目錄下生產一個js文件,就是編譯后的代碼了。

react移動端項目?既然有默認那就有自定義配置,如何做呢?

Ts自定義配置

自定義配置有兩種方式:

  1. 在命令行后加相應配置參數例如你不想將以下代碼編譯成es5的函數形式(配置參考鏈接:compiler-options)

    const fuc = ()=>{console.log(1);
    }
    fuc();
    復制代碼

    你可以

    tsc 文件名.ts --target es6
    復制代碼

    如果需要多個配置,繼續往后寫即可,這里就不詳述了。

  2. 第一種方式如果參數多了看上去很難受,這里我推薦第二種方式:在項目跟目錄新建tsconfig.json文件,我推薦在方法1文檔上找到一個配置參數**--init**初始化tsconfig.json(參考鏈接:tsconfig.json)。

    tsc --init
    復制代碼

    這里我列舉幾個用到的屬性

    {"compilerOptions": {"target": "es5", // 你最終編譯成js模型"lib":["es2017","dom"],// 你使用的一些庫,你可以理解成ts的一些polyfill"module": "ESNext", // 你編譯后的代碼的模式,amd umd esmodule...等等下面詳述"jsx": "react", // jsx 語法糖用哪個"allowJs": true, // 是否允許引入js"checkJs": true, // 是否檢測js文件類型"paths": {"@components/*": ["./src/components/*"],"@utils/*": ["./src/utils/*"],"@view/*": ["./src/view/*"],"@styles/*": ["./src/styles/*"],"@api/*": ["./src/api/*"],"@store/*": ["./src/store/*"],"@decorators/*": ["./src/decorators/*"],"@assets/*": ["./src/assets/*"],},// 別名"strict": true, //嚴格模式"moduleResolution": "node", // 直接看這個吧https://www.tslang.cn/docs/handbook/module-resolution.html"baseUrl": ".", // 配合paths,當符合 paths 規則的文件引入,會采用baseUrl+相應數組列表下查找的方式去找相應文件// "esModuleInterop": true,  // 作用是讓commonjs/esmodule兩種模塊模式正常通信(具體看下一節),作用同下,如果使用了es7相關polyfill不可用會報錯(不確定,個人經驗)。   "allowSyntheticDefaultImports": true, // 往下看模塊機制"experimentalDecorators": true, // 使用裝飾器"rootDir": "./src", // 運行tsc命令時去編譯哪個目錄下的文件配合webpack可以不設置"outDir": "./dist"	// 同樣,其實這個也可以不設置,但是如果不設置你要給js文件寫d.ts(后文會講到)這里會報一個overWrite的錯,作為強迫癥就設置一下吧。},"include": ["src/**/*"], // tsc 會編譯在->rootDir<-內哪些文件"exclude": ["node_modules","dist","build"] // tsc 不會編譯->rootDir<-內的哪些文件
    }
    復制代碼

    Ps:文件新建好了之后如果要編譯當前子文件夾,配置是無效的:

    tsc ./sub/文件名.ts # 配置無效還是默認配置
    復制代碼

模塊轉化

通過編譯后的幾種模塊模式來幫助理解moduleesModuleInteropallowSyntheticDefaultImports配置項;

// 原始代碼
const fuc = ()=>{console.log(1);
}
export default fuc();
// commonjs
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
var fuc = function () {console.log(1);
};
exports.default = fuc();
// amd
define(["require", "exports"], function (require, exports) {
    "use strict";Object.defineProperty(exports, "__esModule", { value: true });var fuc = function () {console.log(1);};exports.default = fuc();
});
復制代碼

原始代碼在 commonjsamd 導出的數據格式其實是這樣子的(如果不知道defineProperty可以查下mdn):

{__esModule: true,default:fuc()
}
復制代碼

當在某處遇到一行代碼引用了

import fuc from '這個地址';
console.log(fuc);
復制代碼

當我們加上esModuleInteropallowSyntheticDefaultImports它會被編譯成

"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
var complie_1 = __importDefault(require("./complie"));
console.log(complie_1.default);復制代碼

require("./complie") 這玩意兒就是上面說的那個對象

然后來分析 __importDefault,首先會識別__esModule變量,如果為true,直接把當前模塊作為導出,否則導出一個對象,對象的default是導出的模塊。

當我們不加上面那兩個選項的時候編譯成

"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
var complie_1 = require("./complie");
console.log(complie_1.default);
復制代碼

小結一下:import variable from 'xx' variable 會被轉成 variable.default;如果配置了esModuleInteropallowSyntheticDefaultImports,如果import的是esmodule直接采用當前模塊,否則把當前模塊放到一個含default的對象中去,default的值就是當前模塊。

OK,接下來我們來解釋這兩個屬性的意義,引入@types/react/index.d.ts一段代碼(d.ts是啥之后再探討)

export = React;
export as namespace React;
復制代碼

我們發現沒有默認值導出值,但是我們想import React from 'react'這種操作就會報錯,OK結論就是這兩句話,但是過程。。很曲折。

再看下另外一種引入和導出方式會如何轉換

// module x
export const a = 1;
export const b = 1;
export const c = 1;
export const d = 1;
export default 10;
// module import module x
import * as all from 'x';
console.log(all)// 轉化過后
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.a = 1;
exports.b = 1;
exports.c = 1;
exports.d = 1;
exports.default = 10;//----------------------------------var __importStar = (this && this.__importStar) || function (mod) {if (mod && mod.__esModule) return mod;var result = {};if (mod != null) for (var k in mod) if (Object.hasOwnProperty.call(mod, k)) result[k] = mod[k];result["default"] = mod;return result;
};
var all = __importStar(require("x"));
console.log(all);
復制代碼

同樣esModule原樣導出,否則取當前對象上的屬性導出(剔除原型鏈上的屬性);這里引入的變量不會被處理成all.default;

webpack配置

我眼中的webpack他是一個資源整合工具,經過:資源->入口->loader + plugin->output這樣一個過程,進行策略整合。本小結不詳細講解配置過程,只是描述下配置思路,具體配置項可點我查看。

首先我們給自己定一個小目標賺他一個億,別走錯片場了,我們的項目需要:

  1. 能解析 ts|tsx 文件;
  2. 能用scss/less文件;
  3. 能跟根據不同命令,打包/運行不同運行環境下的代碼;
  4. 能熱更新;
  5. 移動端線真機調試需要vconsole,但也受命令控制是否引入;
  6. import('xx')實現模塊切割,異步加載模塊;
  7. 公用庫的只想構建一次;
  8. 構建后的代碼,樣式我想autoprefixer并額外導出,js我想壓縮;
  9. 我想引入antd-mobile并能按需引入模塊;

接下來我們一個一個實現這些小目標:

  1. 官推兩個loader:ts-loader/aweasome-typescript-loader,他們都會根據你項目根目錄下的tsconfig.json進行解析。
  2. 配置scss-loader/less-loader
  3. 在package.json中的scripts項分別新增相應參數的命令,可以通過yargs這個庫去拿相應的參數通過DefinePlugin去修改方法體上的代碼。
  4. 那就是配置devServer配置項嘛,當然別忘了加入入HotModuleWebpackPlugin。react的熱更新需要react-hot-loader除了基礎配置以外還需要一個ForkTsCheckerWebpackPlugin插件。
  5. vconsole-webpack-plugin
  6. 啥也不用干,ts已經處理好了
  7. dll??我要更簡單一點,用AutoDllPlugin。
  8. postcss 配下這個插件
  9. ts-import-plugin

具體過程我就不詳述了如果你想看demo就點我吧

轉載于:https://juejin.im/post/5c42c6b76fb9a049fc03d392

版权声明:本站所有资料均为网友推荐收集整理而来,仅供学习和研究交流使用。

原文链接:https://hbdhgg.com/5/166102.html

发表评论:

本站为非赢利网站,部分文章来源或改编自互联网及其他公众平台,主要目的在于分享信息,版权归原作者所有,内容仅供读者参考,如有侵权请联系我们删除!

Copyright © 2022 匯編語言學習筆記 Inc. 保留所有权利。

底部版权信息