目录
第一篇:初始化项目
第二篇:代码规范
第三篇:Webpack 基本配置
第四篇:开发环境设置
第五篇:生产环境设置
第六篇:css、less、scss、图片支持
第七篇:IE11 兼容
第八篇:支持 React
第九篇:支持 Typescript
第十篇:命令行工具
安装
TypeScript 是 JavaScript 的超集,这意味着他支持所有的 JavaScript 语法、并在此之上对 JavaScript 添加了一些扩展。
因此我们不光要安装 typescript 的本体,还必须安装它的 Babel 插件来进行语法转换。
npm install typescript @babel/preset-typescript -D
然后修改 .babelrc :
{ "presets": [ //others "@babel/preset-typescript" ], //others }
之前提过,presets 的执行顺序是从后到前的,所以 typescript 的转换必须放在最后面,才能被最先执行。
配置
打开.vscode/setting.json,输入:
{ //others "eslint.validate": ["javascript", "javascriptreact", "typescript", "typescriptreact"], "typescript.tsdk": "./node_modules/typescript/lib", //others }
eslint.validate:eslint 插件配置
typescript.tsdk:替代 vscode 的 ts 语法智能提示
修改.eslintrc.js 增加新的规则:
module.exports = { parser: '@babel/eslint-parser', extends: [ '@cybozu/eslint-config/globals/kintone', '@cybozu/eslint-config/presets/react-prettier', '@cybozu/eslint-config/presets/react-typescript-prettier', ], rules: { 'react/jsx-filename-extension': [1, { extensions: ['.js', '.jsx', '.ts', '.tsx'] }], }, }
extends:追加了 react-typescript-prettier
typescript.tsdk:替代 vscode 的 ts 语法智能提示
修改 webpack.common.js 文件:
module.exports = { //others extensions: ['.tsx', '.ts', '.js', '.jsx', '.json'], //others module: { rules: [ { test: /\.(tsx?|jsx?)$/, loader: 'babel-loader', options: { cacheDirectory: true }, exclude: /node_modules/, }, //others ], }, }
extensions:后缀名添加 tsx、ts
module.rules:修改 babel-loader 的匹配公式,即,匹配的文件后缀只有 .tsx 、.ts 、 .js、jsx
声明文件
TypeScript 作为 JavaScript 的超集,在开发过程中不可避免要引用其他第三方的 JavaScript 的库。
虽然通过直接引用可以调用库的类和方法,但是却无法使用TypeScript 诸如类型检查等特性功能。
为了解决这个问题,需要将这些库里的函数和方法体去掉后只保留导出类型声明,而产生了一个描述 JavaScript 库和模块信息的声明文件。
通过引用这个声明文件,就可以借用 TypeScript 的各种特性来使用库文件了。
声明文件以 .d.ts 为后缀,绝大部分第三方包的声明文件可以在这里找到。
安装 React 声明文件
npm install @types/react @types/react-dom -D
安装 kintone 声明文件
npm install @kintone/dts-gen -D
tsconfig
tsconfig.json 文件放在项目根目录下,作为 typescript 的编译配置,主要作用:
编译指定文件
定义编译选项
通俗来说,就是 tsc 编译命令的配置文件。
在我们的开发环境中,编译主要交给了 Babel,并不依赖于 tsc。
tsconfig 的作用更偏向与提供编辑器的错误提示。
在控制台输入以下代码来生成此文件:
npx tsc --init
生成的 tsconfig.json 注释内容较多,大家可以日后慢慢学习。先将以下内容覆盖到 tsconfig.json 中
{ "compilerOptions": { "target": "es5", "module": "ESNext", "lib": ["dom", "dom.iterable", "esnext"], "allowJs": true, "jsx": "react", "declaration": true, "noEmit": true, "isolatedModules": true, "strict": true, "noImplicitAny": true, "noUnusedLocals": true, "noUnusedParameters": true, "noImplicitReturns": true, "noFallthroughCasesInSwitch": true, "moduleResolution": "node", "allowSyntheticDefaultImports": true, "esModuleInterop": true, "experimentalDecorators": true, "emitDecoratorMetadata": true, "skipLibCheck": true, "forceConsistentCasingInFileNames": true, "resolveJsonModule": true }, "files": ["./node_modules/@kintone/dts-gen/kintone.d.ts"], "include": ["src/**/*"], "exclude": ["dist", "node_modules"] }
target:编译成哪个版本的 es
module:指定生成哪个模块系统代码
lib:编译过程中需要引入的库文件的列表
allowJs:允许编译 js 文件
jsx:在 .tsx 文件里支持 JSX
declaration:生成相应的 .d.ts 文件
noEmit:不生成输出文件
isolatedModules:将每个文件作为单独的模块
strict:启用所有严格类型检查选项
noImplicitAny:在表达式和声明上有隐含的 any类型时报错
noUnusedLocals:若有未使用的局部变量则抛错
noUnusedParameters:若有未使用的参数则抛错
noImplicitReturns:不是函数的所有返回路径都有返回值时报错
noFallthroughCasesInSwitch:不允许switch的case语句贯穿
moduleResolution:指定模块解析策略
allowSyntheticDefaultImports:允许从没有设置默认导出的模块中默认导入
esModuleInterop:支持 CommonJS 和 ES 模块之间的互操作性
experimentalDecorators:启用实验性的 ES 装饰器
emitDecoratorMetadata:给源码里的装饰器声明加上设计类型元数据
skipLibCheck:忽略所有的声明文件( *.d.ts)的类型检查
forceConsistentCasingInFileNames:禁止对同一个文件的不一致的引用
resolveJsonModule:支持导入 json 模块
files:额外的文件
include:指定需要编译的文件
exclude:忽略文件
编译时的 Typescirpt 类型检查
之前提到过的@babel/preset-typescript,在编译 ts 的过程很粗暴,会直接去掉 ts 的类型声明,然后再用其他 babel 插件进行编译,速度快的同时也会造成一些隐患。
这里给它打上一个补丁,在我们打包或启动本地服务时给予错误提示。
npm install fork-ts-checker-webpack-plugin -D
修改 webpack.common.js 文件:
const ForkTsCheckerWebpackPlugin = require('fork-ts-checker-webpack-plugin') module.exports = { //others plugins: [ new ForkTsCheckerWebpackPlugin({ typescript: { configFile: resolve(__dirname, '../tsconfig.json'), }, }), ], //others }
Demo
最后让我们来做个demo看看效果
在 src 目录下新建 index.tsx
import React from 'react' import ReactDOM from 'react-dom' import './app.css' interface KintoneEvent { record: kintone.types.SavedFields } const App = () => { return ( <div className="app"> <h1>hello, kintone!</h1> </div> ) } kintone.events.on('app.record.index.show', (event: KintoneEvent) => { ReactDOM.render(<App />, kintone.app.getHeaderSpaceElement()) return event })
接下来需要建立 kintone app 的声明文件,推荐大家使用下面的指令自动生成。
npx kintone-dts-gen --host https://${domain}.cybozu.cn -u ${username} -p ${password} --app-id ${appid} -o ./src/fields.d.ts
而这里为了方便直接写了一个最简单的声明文件 fields.d.ts
declare namespace kintone.types { interface Fields {} interface SavedFields extends Fields { $id: kintone.fieldTypes.Id $revision: kintone.fieldTypes.Revision 更新人: kintone.fieldTypes.Modifier 创建人: kintone.fieldTypes.Creator 更新时间: kintone.fieldTypes.UpdatedTime 创建时间: kintone.fieldTypes.CreatedTime key: kintone.fieldTypes.RecordNumber } }
修改 webpack.common.js 中的入口文件,指向 index.tsx
module.exports = { //others entry: { app: resolve(__dirname, '../src/index.tsx'), }, //others }
运行命令看看效果。