使用 Webpack 搭建前端 Typescript 模块化开发最小开发环境

使用 Webpack 搭建前端 Typescript 模块化开发最小开发环境

前言

题中所说的的Typescript最小开发环境是指能够模块化开发Web前端所需的最少组件组成的开发环境,所谓的模块化开发就是能够在分文件的情况下进行模块的分割和整合。虽然在不借助 Webpack 的情况下可以使用 Typescript 自带 namespace 实现模块化的开发,但相比于使用 importexport 这两个关键字,使用 namespace 显得不那么的清晰。但这篇文章还是提供使用 namespace 实现模块化的方法。

使用 namespace 实现模块化

使用 namespace 实现模块化其实很简单,只要把一个 namespace 看作一个模块,把 /// <reference path="**"> 看作 import 语句就可以了,但事实上 namespace 是一个多文件的模块,例如下面代码中的logger1.ts文件和logger2.ts文件可以看作同属于一个模块 Logger,两个文件通过logger2.ts中的///<reference/>连接起来。

// logger1.ts
namespace Logger {
  export function info(info: any) {
    console.log(info);
  }
  export function warn(warn: any) {
    console.warn(warn);
  }
}
// logger2.ts

/// <reference path="./logger1.ts"/>
namespace Logger {
  export function error(error: any) {
    console.error(error);
  }
}

接着就是调用模块中的元素,由于logger2.ts中引用了logger.ts,所以在main.ts中只需要引用logger2.ts。

// main.ts

///<reference path="./logger2.ts"/>
Logger.info('Hello world');

然后就是使用tsc命令将三个文件编译成一个文件,命令如下

> tsc --outFile main.js ./main.ts

然后再文件夹内就有一个main.js文件,在*.html文件中引入这个js文件就能够完成功能的实现。
虽然可以使用多个文件来定义一个模块,但我觉得将一个文件作为单独一个模块更加易于管理,使用单文件模块可以这样改写上述代码

1.将logger2.ts重命名为error.ts, 文件中的代码更改为

// error.ts
namespace ErrorLogger {
  export function error(error: any) {
    console.error(error);
  }
}

2.将logger1.ts重命名为logger.ts,文件中的代码更改为

// logger.ts

/// <reference path="./error.ts"/>
namespace Logger {
  export function info(info: any) {
    console.log(info);
  }
  export function warn(warn: any) {
    console.warn(warn);
  }

  export let error = ErrorLogger.error;
}

3.更改main.ts的代码为

// main.ts

/// <reference path="logger.ts"/>
namespace Main{
  Logger.error('error');
  Logger.warn('warn');
  Logger.info('info');
}

然后重新执行一遍 tsc 命令即可。

从这各部分可以学习到使用 Typescript 的 namespace 进行多文件模块和单文件模块的开发,虽然 namespace 可以实现模块化,但是官方也不推荐单纯的使用 namespace 来进行模块化开发,理由如下

但就像其它的全局命名空间污染一样,它很难去识别组件之间的依赖关系,尤其是在大型的应用中。

所以我么应该使用更加通用的模块化开发方案,那就是ES6中使用import/export关键字的ES Module方案。

Typescript 环境下的 ESModule 模块化开发

ESModule 就是ES6提出的模块化方案,Typescript 的模块化方案取自于ES6,所以只需要掌握ES6 模块化的用法就能够使用 Typescript 的模块化用法。使用 ESModule 改写上面的例子,可以得出以下的代码

// logger.ts
function info(info: String): void {
  console.log(info);
}
function warn(warn: String): void {
  console.warn(warn)
}
function error(error: String): void{
  console.error(error);
}

export {info, warn, error};
// main.ts
import * as Logger from './logger';
Logger.error('Logger Error');
Logger.warn('Logger warn');
Logger.info('Logger info');

这样一看来跟使用 namespace 的差别不大,但其实在 Typescript 中使用 ESModule 的一个好处就是可以按需引入,例如在main.ts中我们只需要 info 方法,那么可以这样改写。

import {info} from './logger';
info('Logger info');

虽然 ESModule 很好,但是这种模块化的写法并不能在浏览器中使用,想要在浏览器中使用模块化只能通过各种打包工具来实现,在下面会介绍配置 Webpack 是的 Webpack 能够自动编译打包 Typescript 文件。

Webpack 配置

Webpack配置主要分为两个部分,分别是识别编译*.ts文件和编写build脚本。首先来看最终效果。

最终效果

在这个例子中有两个文件,分别是time.ts和app.ts,其中app.ts是是入口,两个文件内的代码如下:

// timer.ts
export function timer() {
  return new Date();
}
// main.ts
import {time} from './timer';

let timeEle = document.querySelector('#timer') as Element;
timeEle.innerHTML = time().toString();

然后执行npm run build命令(npm run build的脚本在package.json中定义,稍后会有介绍),然后目录下会多了一个/dist文件夹,下面有一个bundle.js文件,之后在*.html文件中引用这个bundle.js文件即可

<!--index.html-->
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>Document</title>
</head>
<body>
  <div id="timer"></div>
</body>
<script src="./dist/bundle.js"></script>
</html>

运行结果如下

运行结果

初始化文件夹和引入webapck

首先需要使用终端输入npm init初始化当前工作文件夹,文件夹中会多出一个package.json文件,整个文件用于配置npm目录,然后我们需要安装webpack,在终端中输入如下命令完成安装

> npm install --save-dev webpack

接着就是创建Typescript开发环境

创建Typescript开发环境

Typescript开发环境必须通过npm安装typescript模块,在终端中输入以下命令完成安装

> npm install typecript

然后安装webpack需要用到的ts-loader

> npm install --save-dev ts-loader

接着在当前目录创建一个webpack.conf.js配置文件夹,并将以下代码写入其中

const path = require('path');

module.exports = {
  entry: './app.ts',
  devtool: 'inline-source-map',
  module: {
    rules: [
      {
        test: /\.tsx?$/,
        use: 'ts-loader',
        exclude: /node_modules/
      }
    ]
  },
  resolve: {
    extensions: [ '.tsx', '.ts', '.js' ]
  },
  output: {
    filename: 'bundle.js',
    path: path.resolve(__dirname, 'dist')
  }
};

然后在终端输入命令

> webpack --config ./webpack.conf.js

打开index.html即可看到运行结果。

配置build脚本

上面我们使用了npm run build的脚本,只需要子啊package.json的scripts字段中加入下面的语句

"build": "webpack --config ./webpack.conf.js"

然后在终端中使用npm run build即可完成打包功能。

缺点

使用webpack进行模块化开发的缺点主要是打包之后的代码的可阅读性很差,而使用namespace编译后的代码可阅读性非常好。

webpack 打包后代码分析

首先 webpack 打包后的代码中,前面的代码是用于定义一个模块化系统,可以先不深入阅读,模块化系统实现的代码之后就是我们的代码,我们的代码被编译成字符串,使用eval来执行,让人很难读下去。

// bundle.js

 前面一段webpack用于实现模块化的代码,可以自行打开bundle.js中阅读

/***/ "./src/app.ts":
/*!********************!*\
  !*** ./src/app.ts ***!
  \********************/
/*! no static exports found */
/***/ (function(module, exports, __webpack_require__) {

"use strict";
eval("\r\nObject.defineProperty(exports, \"__esModule\", { value: true });\r\nvar timer_1 = __webpack_require__(/*! ./timer */ \"./src/timer.ts\");\r\nvar timeEle = document.querySelector('#timer');\r\ntimeEle.innerHTML = timer_1.time().toString();\r\n\n\n//# sourceURL=webpack:///./src/app.ts?");

/***/ }),

/***/ "./src/timer.ts":
/*!**********************!*\
  !*** ./src/timer.ts ***!
  \**********************/
/*! no static exports found */
/***/ (function(module, exports, __webpack_require__) {

"use strict";
eval("\r\nObject.defineProperty(exports, \"__esModule\", { value: true });\r\nfunction time() {\r\n    return new Date();\r\n}\r\nexports.time = time;\r\n\n\n//# sourceURL=webpack:///./src/timer.ts?");

/***/ })

/******/ });
namespace 编译后代码分析

将原有的代码使用 namespace 语法改写之后再使用tsc --outFile bundle.js ./app.ts命令编译之后的代码如下所示

var Timer;
(function (Timer) {
    function time() {
        return new Date();
    }
    Timer.time = time;
})(Timer || (Timer = {}));
///<reference path="./timer.ts"/>
var App;
(function (App) {
    var timeEle = document.querySelector('#timer');
    timeEle.innerHTML = Timer.time().toString();
})(App || (App = {}));

代码十分的工整,javascript功底比较好的同学应该很容易能够看懂。

总结

这篇文章主要是分析了Typescript中实现模块化的手段,介绍了在Typescript环境下使用namespace和 ESModule 实现前端模块化开发的关键点,也介绍了使用 Webpack 配置 Typescript 开发环境的主要步骤,最后还分析了webpack打包后代码和tsc编译后代码的可读性。

参考资料

Webpack 中文文档
Typescript 中文文档

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

若即

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值