前言
最近在系统的学习typeScript和webpack,今天想搭建一个使用webpack来打包typescript代码的基础框架,如有什么错误或者描述不清的地方,希望大家多多指教!
搭建过程
初始化项目
首先使用npm init初始化项目,在目录下生成package.json文件。package.json的作用就是用来管理我们的项目,里面可以看到我们项目有哪些依赖和命令等。
安装使用webpack 所需要的依赖
webpackwebpack-clitypescriptts-loader
命令:
npm i -D webpack webpack-cli typescript ts-loader
[-D 表示:将安装包添加到开发依赖选项devDependencies,只在开发环境中使用。]
编写webpack的配置文件
在根目录下新建一个文件webpack.config.js,在这个文件里面写webpack的配置项。
接下来我们便开始配置webpack。
引入path模块
path是node里面的一个包,主要用来拼接路径。
const path=require('path');
正式编写配置内容
- 指定
入口文件和打包后文件所在目录以及打包后的文件名
// 正式编写配置信息
//webpack 中所有配置信息都应该写在这里
module.exports={
//指定入口文件
entry:'./src/index.ts',
//指定打包文件所在目录
output:{
//指定打包文件所在目录
path:path.resolve(__dirname,'dist'),
//打包后的文件名
filename:'bundle.js'
}
}
- 指定
webpack打包时要使用的模块
module:{
// 指定要加载的规则
rules:[
{
//test 指定的时规则生效的文件
test:/\.ts$/,
//要使用的loader
use:'ts-loader',
//要排除的文件
exclude:/node_modules/
}
]
}
这时webpack便可以使用了,但是光配置了webpack还不行,因为我们是需要使用webpack来打包ts代码,所以我们还需要配置ts。
编写typescript的配置文件
在根目录下新建一个文件tsconfig.json,在这个文件里面写typescript的配置项。
接下来我们便开始配置typescript。
{
//编译器选项
"compilerOptions": {
//指定要使用的模块化规范
"module": "ES2015",
//指定编译后js的版本
"target": "ES2015",
// 指定是否使用严格模式
"strict": true
}
}
执行初次打包
设置命令
我们设置好了tsconfig和webpack.config.json便可以启动试试,看看能否成功按照我们所想的打包。在执行打包之前,我们先在package.json中添加打包命令。
"scripts": {
"build":"webpack"
},
打包
命令:npm run build
结果:
我们可以看到在dist目录下生成了一个名为
bundle.js的文件,文件里面的内容为我们在ts文件中写的内容:
index.ts:
bundle.js:
这样,使用webpack 打包ts代码的基础功能便可以了。接下来我们便再做一些配置,使框架更加完善。
webpack自动创建html文件并在浏览器中打开
如果打包之后的内容我们想在浏览器中看到,这时应该怎么做呢?
可能有小伙伴会想“这还不简单,我直接创建个html文件,然后引入打包之后的js,再在浏览器中打开不就ok了嘛”,这样做的确可以,但是有个问题,如果我们打包之后不止一个js文件呢?如果我们有其他的css文件呢?难道我们要每次打包之后都去手动改一下html内容吗?
接下来,我们就使用webpack的插件 —— html-webpack-piugin来实现自动引入文件,打包之后有几个文件便引入几个文件。
自动生成打包后的html并引入打包后的文件
安装html-webpack-plugin
命令:npm i -D html-webpack-plugin
引入
// 引入html-webpack-plugin
const htmlWebpackPlugin=require("html-webpack-plugin");
配置webpack 插件
在moudle后添加plugins配置:
//配置webpack 插件
plugins:[
//自动生成HTML文件并引入文件
new htmlWebpackPlugin(),
]
配置好了之后,我们来试一下:
可以看到
dist目录下新增了个html文件,html 内容为:
可以看到bundle.js已经自动引入进来了。
如果你想自定义html的title的话,可以这样改一下,例如:
//配置webpack 插件
plugins:[
new htmlWebpackPlugin({
title:"土豆奥利奥"
}),
]
这样打包之后,便有了:
如果你希望打包后的html文件是按照自定义的结构来展示的,那你可以指定一个模板html,在模板html中定义好结构之后,添加配置:
//配置webpack 插件
plugins:[
new htmlWebpackPlugin({
// title:"土豆奥利奥",
//定义模板
template:'./src/index.html'
}),
]
模板html内容
打包后:
这样便可以按照自定义的结构来展示了。
在浏览器中自动打开打包后的html文件
想在打包之后在浏览器中自动打开网页,需要使用webpack的另一个插件webpack-dev-server。
安装
命令:npm i -D webpack-dev-server
设置命令
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
"build": "webpack",
"start":"webpack serve --open Chrome.exe"
},
执行命令
npm start
结果:
这个插件还能在内容变化之后,自动编译刷新。 所以我们在开发时就可以专注于写代码,不用去手动编译与操作浏览器
两个小问题
每次打包前,先删除上次打包的文件,再生成新的打包文件,确保每次编译文件都是最新的文件打包而成的
要实现这个功能需要使用一个新的插件:clean-webpack-plugin。
同样,先安装npm i -D clean-weboack-plugin。
再使用:
//引入clean-webpack-plugin
const { CleanWebpackPlugin } = require("clean-webpack-plugin");
//配置webpack 插件
plugins: [
// CleanWebpackPlugin
new CleanWebpackPlugin(),
//使用htmlWebpackPlugin
new htmlWebpackPlugin({
// title:"土豆奥利奥",
//定义模板
template: "./src/index.html",
}),
],
这样便配置好了,也实现了每次编译前先删除上次编译产生的文件的功能。
多个模块之间的引入
例如:在index.ts中,我们引入另一个ts文件:
这种时候我们去执行npm run build便会报错:
为什么会报错呢?
这是因为这里我们引入的test是一个ts文件,但是在webpack中默认是不知道ts可以作为模块使用的。webpack不知道哪些文件可以被当作模块使用,所以我们需要设置一下,告诉webpack哪些文件可以被当作webpack 使用!
如何设置呢?
在plugins后添加resolve设置。
//用来设置引用模块
resolve: {
extensions: [".ts", ".js"],
},
设置完成后,再执行下build:
。
引入Babel,解决兼容性问题
为了解决不同浏览器中的兼容性问题,我们可以在webpack中引入babel.
安装
- @babel/core
- @babel/preset-env(
预制环境) - babel-loader
- core-js(
让老版本的浏览器能够使用新标准的内容)
配置webpack.config.json
在module里配置babel:
// 指定webpack打包时要使用的模块
module: {
// 指定要加载的规则
rules: [
{
//test 指定的时规则生效的文件
test: /\.ts$/,
//要使用的loader
use: [
//配置babel
{
//指定loader
loader: "babel-loader",
options: {
//设置预定义的环境
"presets": [
[
//指定环境插件
"@babel/preset-env",
//配置信息
{
//指定浏览器版本,要兼容的目标浏览器
"targets": {
"chrome": "88",
"ie": "11",
},
//指定corejs版本
"corejs": "3",
//使用corejs的方式“usage”,表示按需加载
"useBuiltIns": 'usage'
},
]
],
},
},
"ts-loader",
],
//要排除的文件
exclude: /node_modules/,
},
],
},
打包之后的文件:
可以看到之前的
const 已经被编译成了var
设置corejs,确保新标准的特性老版本浏览器也可以使用。
例如,我们在index.ts中打印Promise,
在老版本浏览器中,这时Promise是无法正确获取的,因为老版本的浏览器根本没有Promise,即使使用了babel也没法正确处理,那怎么办呢? 如图,Promise并没有被Babel解析处理:
答案是:使用core-js,原理是:老版本浏览器没有Promise,那core-js就给它一个自己实现的Pormise,这样就可以正确使用Promise了。
要配置的内容为:
//指定corejs版本
"corejs": "3",
//使用corejs的方式“usage”,表示按需加载
"useBuiltIns": 'usage'
配置之后,打包的结果如图:
坑点
那以上所有都配置好了,就可以正确在老版本浏览器中运行起来了吗?
答案是:不一定,因为还有一个坑:
我们可以看到,即使设置好了babel和corejs,编译出来的bundle.js中依旧存在箭头函数,这是为什么呢?
这其实并不是babel的锅,最外层的立即执行函数(箭头函数)是webpack打包时自动生成的,这个部分根本就没有经过babel!这个时候就需要设置webpack配置:
//指定打包文件所在目录
output: {
//指定打包文件所在目录
path: path.resolve(__dirname, "dist"),
//打包后的文件名
filename: "bundle.js",
//告诉webpack不适用箭头函数
environment: {
arrowFunction: false
}
},
这时可以看到原来的箭头函数已经转为普通函数了。
总结
以上,便是使用webpack打包TypeScript代码: 从配置环境到生成可执行文件的全部内容了。如果有需要源码的小伙伴可以到:github.com/wz156700/we… 下载源码。如果有错误之处,希望大家留言之处,谢谢大家了。