TypeScript(3): 使用WebPack工具
1. 体验webpack
同样,我们还是先建立一个新的项目目录。今天的项目就叫03_webpack
,建立目录不再演示了,现在我们通过cd
命令切换到该目录。紧接着,输入如下命令:
npm init -y
可以看到目录03_webpack
下生成了一个名为package.json
的文件,如图:
这个文件先放在这,一会我们还要用它。
接着,在该文件夹中本地局部安装webpack,即运行以下命令:
npm install webpack --save-dev
运行该命令需要网络,命令将从网络下载webpack模块以及其依赖模块,存放在该项目文件夹中新建的名为node_modules
的子目录中,并生成了package-lock.json
文件。如图:
对了,细心的你可能已经发现除了以上变化以外,package.json
文件中还多了一项为devDependencies
的配置,如图上所示。
不过这还没完成,接着请继续输入以下命令安装webpack-dev-server:
npm install webpack-dev-server
也可以用webpack的脚手架CLI(命令行工具)进行安装,如下:
npm install --save-dev webpack webpack-cli
如果需要使用webpack打包ts文件,需要安装ts-loader:
npm install --save-dev ts-loader
现在,在我们的node_modules
目录中自然也多了很多新安装的包,包括webpack-dev-server
及其相关的依赖。但是我们所关注的,到底还是num配置文件package.json
,可以看到,现在又多了新的内容
即webpack
和webpack-dev-server
安装下来,该文件里多了以下两个配置项:
"devDependencies": { "webpack": "^5.31.0" }, "dependencies": { "webpack-dev-server": "^3.11.2" }
现在我们对package.json
文件进行修改——在"script"部分增加一个快速启动webpack-dev-server
服务的脚本:
{ // ...此处省略其他内容 "script"{ "test": "echo \"Error: no test specified\" && exit 1", "dev": "webpack-dev-server --open --config webpack.config.js" }, }
如图:
当然上面指向的这个脚本"webpack.config.js
"目前还并不存在,因此现在让我们来创建它,并添加以下内容:
// "./webpack.config.js": var path = require("path"); var config = { entry:{ // 指示 webpack 应该使用哪个模块作为构建其内部 依赖图的开始 main: "./main" // 表示当前目录下的"main.js"文件 }, output:{ // 这些内容告诉 webpack 在哪里输出它所创建的 bundle,以及如何命名这些文件 path: path.join(__dirname, "./dist"), // 输出的根目录 publicPath: "/dist/", // 相对于输出根目录打包存储文件的目录 filename: "main.js" // 存储的文件名 } }; module.exports = config;
先让我们解释以下webpack此配置文件吧。
首先,在配置中设定的入口是该项目目录下的"main.js"文件,我们并没建立这个文件,因此现在来创建它,并简单随意地写入一条语句:
// main.js document.write("Hello webpack...")
然后必须认识到webpack内部实现其实我们已经没必要关心了,当我们使用命令npm install webpack
以及webpack-dev-server
后,相关的脚本以及其它文件已经被安装到相应的文件夹中。虽然webpack并非只是一个名为webpack.config.js
的配置文件,但是对我们使用者而言却往往只需要关系通过该文件将必要的参数告诉给webpack以让其在Node.js
环境下运行时知道该满足哪些特定的运行参数。
然后再来看配置文件中有关的代码。在本配置中核心部分是如下框架:
var config = { }; module.exports = config;
其中:
config={}
顾名思义,里面描述的是具体的一些配置参数,一般至少包括入口(entry)
、输出(output)
的信息。module.exports
,如果使用ECMAScript 6.0语法则相当于写成export default config
。module.exports
用于暴露我们的配置给webpack获取。
这里有一些概念需要理解。起初在JavaScript中是没有模块
的概念的。当前端工程引入来源于后端的模块
话概念后,一个.js
文件可视为一个模块(module),它可以被任意其他的模块引入。
也就是引入该模块的其它模块能够拥有该模块中所持有的对象。这里有一个问题是被引入的对象都是在原模块自己的作用域中而发起引入的那个模块虽然获取到了被引入的对象,但是并不能访问作用域里的东西。这里的所以提供了export实际上就是决定为调用模块者提供的暴露接口。
其实在部分功能上,又有点像Java中的包。写过Java的同学应该熟悉如果你的一个文件要作为可以被导入的模块,那么你就要用package
语句在该文件上面声明这个取决于路径的模块名(一般是公司的反域名)。比如
package org.apache.poi.hssf.usermodel;
这个package
要说真又什么作用也就是给Java中import
语句用的,这样你在调用该模块的时候就可以:
import org.apache.poi.hssf.usermodel.文件名;
虽然有一些区别,说到底ECMAScript中的exports
和Java中的packsge
实际上都是为import
提供暴露服务。
- 鉴于有同学可能不了解Node.js,最后顺便提以下开头的那一条代码。
开头的那句var path = require("path");
只是因为我们在后面使用了path.join()
函数,该函数的格式如下:
path.join([path1][, path2][, ...])
- 这是Node.js的
Path模块
中的一个函数,用于连接两端路径。在很多编程语言的内建模块中都有这个函数,比如在Python中需要用import os.path
导入Python的Path模块,并使用path.join(path1, path2)
连接,这里是一样的。
而Node.js的语句var path = require("path")
就相当于在Python中的import os.path
,仅此而已。
有小朋友问,直接使用字符串相加连接两端路径它不乡吗,比如:
path1 = "D://code" path2 = "2" path = path1 + "//" + path2
- 这种写法不仅麻烦而且无法跨平台。因为不同操作系统上的路径是不一样的。
再回到webpack。可以看到,我们只是为了提高可读性,将所有的配置写到config
所定义的变量中。
现在,我们来写一个html文件,并第一次使用webpack对这个项目进行打包。
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>03_webpack</title> </head> <body> <div id="app"> Hello html! </div> <script type="text/javascript" src="/dist/main.js"></script> </body> </html>
现在,我们的项目看起来是这样的:
打开终端,进入该项目文件夹,运行我们的项目:
npm run dev
在浏览器中输入url:http://127.0.0.1:8887/
,可以看到显示以下内容:
这里的地址127.0.0.1
为本机回送地址,目前的主流操作系统中配置了本地的域名解析,将localhost
解析到127.0.0.1
,因此你也可以输入http://localhost:8887
,8887即我们所使用的端口号。还记得吗,ip和端口号是我们在package.json
中的script
下配的:
好的,如果你的程序也顺利跑起来了那么,让我们来打包吧,执行以下命令:
webpack --progress --hide-modules
2. 使用webpack打包编译ts文件
本小节主要介绍如何使用webpack来编译ts文件为浏览器能够执行的js文件。
现在,请自行准备好一个项目文件夹用于今天的项目。
在项目的更目录下新建一个ts文件hello.ts
,用于写TypeScript代码:
// hello.ts console.log("Hellow WebPack!")
安装webpack:
npm install --save-dev webpack webpack-cli
ts-loader
是一个用于Webpack的TypeScript加载器,如果使用yarn工具安装,则命令为:
yarn add ts-loader --dev
或者
npm install ts-loader --save-dev
这里,由于我们之前是全局安装的TypeScript
,因此我们需要链接它:
npm link typescript
然后,初始化一个nodejs项目配置文件tsconfig.json
:
npm init -y
接着,新建webpack.config.js
文件,输入以下内容:
const path = require('path'); // 对Node.js地标准库`path`进行导包 module.exports = { entry:'./hello.ts', // 打包文件入口 output:{ filename:'hello.js', // 输出文件名称 path:path.resolve(__dirname,'js') // 输出文件夹名为'es5',需要加上前面地路径构成绝对路径 }, mode: 'development', module:{ // all files with a `.ts` or `.tsx` extension will be handled by `ts-loader` rules: [{ test: /\.tsx?$/, use: 'ts-loader', exclude: /node_modules/ }] }, resolve: { // Add `.ts` a resolvable extension. extensions: ['.ts'] }, }
接着,在tsconfig.json
的script
字段中添加启动webpack的命令:
"scripts": { "pack": "webpack" },
在改=该项目目录下运行:
npm run pack
可以看到生成了一个./js
目录,在该目录下生成了一个hello.js
文件。
需要指出的是,使用webpack生成的js
文件和tsc
命令生成的js
文件完全是两码事!
tsc
命令只是对TypeScript
代码进行了翻译,对应成为了JavaScript
代码。而webpack生成的js文件中添加了很多webpack自己的东西。