TS开发环境运行方式对比
ts-node可以直接运行ts文件,但是浏览器不能直接运行ts,需要转成js。js有不同的规范,所以ts转js时,可以转换的目标规范也可以不同,具体配置如图所示:
以下三种实现方式
命名空间使用:CommonJS规范
import方式引入:ES6 Module,转译成AMD规范
Parcel打包使用:打包工具方式
命名空间使用
没有命名空间
编译后都是
var
声明的全局变量,过多的全局变量会让代码变得不可维护有命令空间
通过
namespace
定义,通过export
暴露出去只有暴露出去才是全局的,其他的不会造成全局污染
减少全局变量,实现基本的封装
新增
src/components.ts
文件:组件化实现,每个类(class
)都使用了export
导出,采用了命名空间(namespace
)
namespace Components { export class Header { constructor() { const elem = document.createElement("div"); elem.innerText = "This is Header"; document.body.appendChild(elem); } } export class Content { constructor() { const elem = document.createElement("div"); elem.innerText = "This is Content"; document.body.appendChild(elem); } } export class Footer { constructor() { const elem = document.createElement("div"); elem.innerText = "This is Footer"; document.body.appendChild(elem); } } } 复制代码
新增
src/page.ts
文件
namespace Home { export class Page { constructor() { new Components.Header(); new Components.Content(); new Components.Footer(); } } } 复制代码
新增
index.html
文件
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" /> // 引入文件 <script src="./build/page.js"></script> <title>Document</title> </head> <body> // 执行文件 <script>new Home.Page();</script> </body> </html> 复制代码
编辑 tsconfig.json 文件
outFile
配置项:用来处理多个文件生成一个文件,避免每次增加文件都要在入口文件 index.html
中引入一下
使用前:生成
build/page.js
和build/components.js
两个文件,index.html
中也需要引入两个使用后,仅生成
build/page.js
文件,而且要更改"module":"amd"
配置,由commonjs
改为amd
{ "compilerOptions": { // "module": "commonjs" "module": "amd", "outFile": "./build/page.js", /* 生成一个文件 */ "rootDir": "./src", /* ts文件位置目录 */ "outDir": "./build", /* 编译后js文件存放目录 */ } } 复制代码
运行效果
tsc // ts文件编译为js文件 open index.html // 打开页面,查看效果 复制代码
import方式引入
CommonJS
:浏览器不支持,用于服务端,如NodeJS,webpack;通过require同步加载模块,通过 exports 或 module.exports 导出AMD
:异步模块定义,支持浏览器端,RequireJS;通过define定义模块,require加载模块;提前执行,依赖前置CMD
:同步模块定义,支持浏览器端,SeaJS;延迟执行,依赖就近;ES6 Module
:import/export;无法直接在浏览器中执行,需要转译
修改
src/components.ts
文件,去除空间namespace
,直接使用 ES6 的export
导出修改
src/page.ts
文件,通过 ES6 的import
引入
import { Header, Content, Footer } from "./components"; // 必须要加 default 关键字,才能引用到 export default class Page { constructor() { new Header(); new Content(); new Footer(); } } 复制代码
问题:使用tsc
命令编译后生成 build/*.js 文件,打开 index.html 会报错。
原因:编译好的代码都是define
开头的( AMD
规范),可以在 Node 中直接运行,*不能直接在浏览器中运行*
,需要其他库(如require.js
)的支持
修改
index.html
文件:修改完成后可以正常显示
<head> // 引入require.js,浏览器就可以正常解析 define 语法了 <script src="https://cdnjs.cloudflare.com/ajax/libs/require.js/2.3.6/require.js"></script> </head> <body> <script> // 执行方式也需要修改 require(["page"], function (page) { new page.default(); }); </script> </body> 复制代码
Parcel打包使用
上面通过 require
方式引入,用起来步骤太多,比较麻烦。
可以通过 webpack
和 Parcel
打包工具处理,简化流程。
Parcel官网地址:v2.parceljs.cn/getting-sta…
还是借助上面 tsdemo 示例进行改造:
更改index.html文件,直接引入ts文件;且移动到src目录下
<html lang="en"> <head> // ... // 必须要加type="module",不然会报错 // page.ts最后面加上 "new Page()", 执行代码 <script type="module" src="./page.ts"></script> </head> </html> 复制代码
修改tsconfig.json配置文件:只更改 rootDir 的值,其他的还原
{ "compilerOptions": { "module": "commonjs" // "module": "amd", // "outFile": "./build/page.js", "rootDir": "./src", // "outDir": "./build", } } 复制代码
安装Parcel
// yarn 安装 yarn add --dev parcel // 或者 npm 安装 npm install --save-dev parcel 复制代码
修改package.json文件
{ "name": "tsdemo", "version": "1.0.0", "source": "src/index.html", // add "scripts": { "start": "parcel", // add "build": "parcel build" // add }, "devDependencies": { "parcel": "^2.0.1" // add } } 复制代码
启动服务
// 运行命令 npm run start // 打开页面访问 http://localhost:1234 复制代码
报错如下图所示: @parcel/transformer-js: Browser scripts cannot have imports or exports.
报错原因:代码中用到了ES6的import/export,Parcel不支持
解决办法:就是引入ts文件时,添加 type="module"
效果展示
作者:时光足迹
链接:https://juejin.cn/post/7031076756022886431