使用webpack打包TypeScript代码: 从配置环境到生成可执行文件

913 阅读3分钟

前言

最近在系统的学习typeScriptwebpack,今天想搭建一个使用webpack来打包typescript代码的基础框架,如有什么错误或者描述不清的地方,希望大家多多指教!

搭建过程

初始化项目

首先使用npm init初始化项目,在目录下生成package.json文件。package.json的作用就是用来管理我们的项目,里面可以看到我们项目有哪些依赖和命令等。

安装使用webpack 所需要的依赖

  • webpack
  • webpack-cli
  • typescript
  • ts-loader

命令: npm i -D webpack webpack-cli typescript ts-loader

[-D 表示:将安装包添加到开发依赖选项devDependencies,只在开发环境中使用。]

编写webpack的配置文件

在根目录下新建一个文件webpack.config.js,在这个文件里面写webpack的配置项。 接下来我们便开始配置webpack

引入path模块

pathnode里面的一个包,主要用来拼接路径

const path=require('path');

正式编写配置内容

  1. 指定入口文件打包后文件所在目录以及打包后的文件名
// 正式编写配置信息
//webpack 中所有配置信息都应该写在这里
module.exports={
    //指定入口文件
    entry:'./src/index.ts',
    //指定打包文件所在目录
    output:{
        //指定打包文件所在目录
        path:path.resolve(__dirname,'dist'),
        //打包后的文件名
        filename:'bundle.js'
    }
}
  1. 指定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
    }
}

执行初次打包

设置命令

我们设置好了tsconfigwebpack.config.json便可以启动试试,看看能否成功按照我们所想的打包。在执行打包之前,我们先在package.json中添加打包命令

"scripts": {
    "build":"webpack"
  },

打包

命令:npm run build

结果: image.png 我们可以看到在dist目录下生成了一个名为bundle.js的文件,文件里面的内容为我们在ts文件中写的内容:

index.ts: image.png

bundle.js:

image.png

这样,使用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(),
    ]
    

配置好了之后,我们来试一下:

image.png 可以看到dist目录下新增了个html文件html 内容为:

image.png 可以看到bundle.js已经自动引入进来了。

如果你想自定义html的title的话,可以这样改一下,例如:

//配置webpack 插件
    plugins:[
        new htmlWebpackPlugin({
            title:"土豆奥利奥"
        }),
    ]

这样打包之后,便有了:

image.png

如果你希望打包后的html文件是按照自定义的结构来展示的,那你可以指定一个模板html,在模板html中定义好结构之后,添加配置:

//配置webpack 插件
    plugins:[
        new htmlWebpackPlugin({
            // title:"土豆奥利奥",
            //定义模板
            template:'./src/index.html'
        }),
    ]

模板html内容

image.png

打包后:

image.png

这样便可以按照自定义的结构来展示了。

在浏览器中自动打开打包后的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

结果:

image.png

这个插件还能在内容变化之后,自动编译刷新。 所以我们在开发时就可以专注于写代码,不用去手动编译与操作浏览器

两个小问题

每次打包前,先删除上次打包的文件,再生成新的打包文件,确保每次编译文件都是最新的文件打包而成的

要实现这个功能需要使用一个新的插件: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文件:

image.png

image.png

这种时候我们去执行npm run build便会报错:

image.png

为什么会报错呢?

这是因为这里我们引入的test是一个ts文件,但是在webpack中默认是不知道ts可以作为模块使用的。webpack不知道哪些文件可以被当作模块使用,所以我们需要设置一下,告诉webpack哪些文件可以被当作webpack 使用!

如何设置呢? 在plugins后添加resolve设置。

  //用来设置引用模块
  resolve: {
    extensions: [".ts", ".js"],
  },

设置完成后,再执行下build:

image.png

引入Babel,解决兼容性问题

为了解决不同浏览器中的兼容性问题,我们可以在webpack中引入babel.

安装

  1. @babel/core
  2. @babel/preset-env(预制环境)
  3. babel-loader
  4. 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/,
      },
    ],
  },

打包之后的文件:

image.png 可以看到之前的const 已经被编译成了var

设置corejs,确保新标准的特性老版本浏览器也可以使用。

例如,我们在index.ts中打印Promise,

image.png

在老版本浏览器中,这时Promise是无法正确获取的,因为老版本的浏览器根本没有Promise,即使使用了babel也没法正确处理,那怎么办呢? 如图,Promise并没有被Babel解析处理:

image.png

答案是:使用core-js,原理是:老版本浏览器没有Promise,那core-js就给它一个自己实现的Pormise,这样就可以正确使用Promise了。 要配置的内容为:

    //指定corejs版本
    "corejs": "3",
    //使用corejs的方式“usage”,表示按需加载
    "useBuiltIns": 'usage'

配置之后,打包的结果如图: image.png

坑点

那以上所有都配置好了,就可以正确在老版本浏览器中运行起来了吗?

答案是:不一定,因为还有一个坑:

image.png

我们可以看到,即使设置好了babelcorejs,编译出来的bundle.js中依旧存在箭头函数,这是为什么呢?

这其实并不是babel的锅,最外层的立即执行函数(箭头函数)是webpack打包时自动生成的,这个部分根本就没有经过babel!这个时候就需要设置webpack配置:

//指定打包文件所在目录
  output: {
    //指定打包文件所在目录
    path: path.resolve(__dirname, "dist"),
    //打包后的文件名
    filename: "bundle.js",

    //告诉webpack不适用箭头函数
    environment: {
      arrowFunction: false
    }
  },

image.png

这时可以看到原来的箭头函数已经转为普通函数了。

总结

以上,便是使用webpack打包TypeScript代码: 从配置环境到生成可执行文件的全部内容了。如果有需要源码的小伙伴可以到:github.com/wz156700/we… 下载源码。如果有错误之处,希望大家留言之处,谢谢大家了。