likes
comments
collection
share

面试官:你就只会 npm run build 吗?(Webpack 配置 Vue+Ts)

作者站长头像
站长
· 阅读数 12

写在前面

多亏上次 Webpack打包类库踩坑(上期文章),让我重新想起来 Webpack 等相关打包工具的重要性,稍微做了下调研,发现其实很多稍微有些工作经验的人,对于 Webpack 的了解程度也都普遍偏低,很多时候大家也就知道 npm run build,并不知道具体 run了之后 Webpack 做了什么,还有一些原因是,平时大家大部分的时间都是在完成业务的开发,打包上线这类的工作基本上是团队 master 来处理,导致了很多人并没有机会接触到 Webpack 配置,更不用说对相关配置进行修改、优化。所以,这次我将我之前进行 Webpack 基础配置练习过程的笔记分享出来,希望能够给想要了解 Webpack 配置的朋友进行参考,步骤详细,简单,希望初学的小白能够快速入手,大佬的话挑挑毛病,你们的意见是我们晚辈不可或缺的营养。

配置环境

本文采用 当下比较火的 Ts + Vue 作为联系载体,Webpack 采用的是 Webpack@5,希望能够在这一次练习配置 Webpack 的过程中顺便也熟悉一下 Ts + Vue 这个组合,方便后期迁移技术栈

一、Webpack 配置

1、npm、ts 初始化并安装 webpack 相关包

npm init -y
tsc --init
npm i webpack webpack-cli webpack-dev-server -D

2、按结构创建以下文件及文件夹

/build/webpack.base.config.js
/build/webpack.dev.config.js
/build/webpack.pro.config.js
/build/webpack.config.js

/src/tpl/index.html

/src/index.ts

3、在 /src/tpl/index.html 中写入模板,注意 class='app' 为后面一切修改的识别点

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Typescript</title>
</head>
<body>
  <div class="app"></div> 
</body>
</html>

4、在 /build/webpack.base.config.js 中写入基础配置

const HtmlWebpackPlugin = require('html-webpack-plugin')
module.exports = {
  // 入口文件
  entry: "./src/index.ts",
  // 输出文件名称,默认输出到根目录
  output: {
    filename: "app.js"
  },
  // 配置需要编译的文件扩展名
  resolve: {
    extensions: ['.js','.ts', 'tsx']
  },
  // 配置需要经过 ts-loader 进行编译的文件
  module: {
    rules: [
      {
        test: /\.tsx?$/i,
        use: [{
          loader: "ts-loader"
        }],
        exclude: /node_modules/
      }
    ]
  },
  // 添加 html 插件,并指定模板文件
  plugins: [
    new HtmlWebpackPlugin({
      template: "./src/tpl/index.html"
    })
  ]

}

5、在 /build/webpack.dev.config.js 中添加开发环境配置

// 预留开发环境相关配置
module.exports = {}

6、在 /build/webpack.pro.config.js 中添加生产环境环境配置

const { CleanWebpackPlugin } = require('clean-webpack-plugin') 
module.exports = {
  // 每次编译删除旧的,只保留最新的
  plugins: [
    new CleanWebpackPlugin()
  ]
}

7、在 /build/webpack.config.js 中将所有配置引入

const {merge} = require('webpack-merge')
const baseConfig = require('./webpack.base.config')
const devConfig = require('./webpack.dev.config')
const proConfig = require('./webpack.pro.config')

// 通过判断环境参数,决定将基础配置和生产环境配置 / 开发环境配置合并
module.exports = (env, argv) => {
  let config = argv.mode === 'development' ? devConfig : proConfig
  return merge(baseConfig, config)
}

8、安装 webpack 配置过程中使用到的插件

npm i typescript ts-loader html-webpack-plugin clean-webpack-plugin webpack-merge

9、在package.js 中配置webpack 启动脚本

"scripts": {
    "start": "webpack-dev-server --mode=development --config ./build/webpack.config.js",
    "build": "webpack --mode=production --config ./build/webpack.config.js"
  },

二、配置 vue

1、 npm i vue 安装vue

2、 在/src/index.ts中引入 Vue 并创建实例

import Vue from 'vue'
let app = new Vue({
  el: '.app',
  data: {
    name: 'typescript',
  },
  template: '<h1>Hello {{ name }}</h1>'
})

3、 运行npm start 编译后运行,报错

面试官:你就只会 npm run build 吗?(Webpack 配置 Vue+Ts)

4、 /build/webpack.base.config.js 中的 resolve 配置项中加入别名 vue ,引入完整ES6版本的Vue,成功运行Vue

resolve: {
    extensions: ['.js','.ts', 'tsx'],
    alias: {
      vue: 'vue/dist/vue.esm.js'
    }
  },

面试官:你就只会 npm run build 吗?(Webpack 配置 Vue+Ts)

5、接下来尝试引入组件,在 /src/components 中创建 Hello.vue 组件

<template>
  <h1>Hello {{ name }} </h1>
</template>

<script lang="ts">
import Vue from 'vue'
export default Vue.extend({
  data(){
    return {
      name: 'typescript'
    }
  }
})
</script>

<style scoped>
h1 {
  color: cadetblue;
}
</style>

6、在 /src/index.ts 中引入 Hello.vue 组件

import Vue from 'vue'
// 引入注意加上vue后缀,不加后缀ts会报错
import Hello from './components/Hello.vue'

let app = new Vue({
  el: '.app',
  components: {
    Hello
  },
  template: '<Hello />'
})

7、编译器报错提示,为 .vue文件添加 vue.shims.d.ts 定义文件

面试官:你就只会 npm run build 吗?(Webpack 配置 Vue+Ts)

declare module '*.vue' {
  import Vue from 'vue'
  export default Vue
}

8、解析 .vue 文件需要安装相关插件

npm i -D vue-loader vue-template-compiler css-loader

9、修改 webpack 配置

在 /build/webpack.base.config.js 中的 resolve 的 extensions 中添加 .vue 扩展名

resolve: {
    extensions: ['.js','.ts', 'tsx', 'vue'],
    alias: {
      vue: 'vue/dist/vue.esm.js'
    }
},

在 module 中的 rules 添加 vue-loader、vue-style-loader、css-loader,并在 ts-loader 的 options 中加入appendTsSuffixTo,为 .vue 文件自动添加 ts 后缀,方便 ts-loader 解析

module: {
    rules: [
      {
        test: /\.vue$/,
        loader: 'vue-loader'
      },
      {
        test: /\.tsx?$/i,
        use: [{
          loader: "ts-loader",
          options: {
            appendTsSuffixTo: [/\.vue$/]
          }
        }],
        exclude: /node_modules/
      },
      {
        test: /\.css$/,
        use: [
          'vue-style-loader',
          'css-loader'
        ]
      }
    ]
  },

最后添加 vue-loader 插件

const { VueLoaderPlugin } = require('vue-loader')
module.exports = {
  .......
  plugins: [
    ......
    new VueLoaderPlugin()
  ]
}

10、运行 npm start 进行编译,至此整个配置过程结束

疑难杂症

由于目前许多 NPM 包迭代非常频繁,因此在复现本文配置过程中可能会出现因为插件版本不兼容而导致打包失败,所以附上各个配置文件供大家参考:

// package.json
{
  "name": "vue-ts",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "start": "webpack-dev-server --mode=development --config ./build/webpack.config.js",
    "build": "webpack --mode=production --config ./build/webpack.config.js"
  },
  "keywords": [],
  "author": "",
  "license": "ISC",
  "devDependencies": {
    "clean-webpack-plugin": "^4.0.0",
    "css-loader": "^6.5.1",
    "html-webpack-plugin": "^5.5.0",
    "ts-loader": "^9.2.6",
    "typescript": "^4.5.2",
    "vue-loader": "^15.9.8",
    "vue-template-compiler": "^2.6.14",
    "webpack": "^5.64.4",
    "webpack-cli": "^4.9.1",
    "webpack-dev-server": "^4.6.0",
    "webpack-merge": "^5.8.0"
  },
  "dependencies": {
    "vue": "^2.6.14"
  }
}
// webpack.base.config.js 完整配置
const HtmlWebpackPlugin = require('html-webpack-plugin')
const { VueLoaderPlugin } = require('vue-loader')
module.exports = {
  entry: "./src/index.ts",
  output: {
    filename: "app.js"
  },
  resolve: {
    extensions: ['.js','.ts', 'tsx', 'vue'],
    alias: {
      vue: 'vue/dist/vue.esm.js'
    }
  },
  module: {
    rules: [
      {
        test: /\.vue$/,
        loader: 'vue-loader'
      },
      {
        test: /\.tsx?$/i,
        use: [{
          loader: "ts-loader",
          options: {
            appendTsSuffixTo: [/\.vue$/]
          }
        }],
        exclude: /node_modules/
      },
      {
        test: /\.css$/,
        use: [
          'vue-style-loader',
          'css-loader'
        ]
      }
    ]
  },
  plugins: [
    new HtmlWebpackPlugin({
      template: "./src/tpl/index.html"
    }),
    new VueLoaderPlugin()
  ]
}
// webpack.config.js 完整配置
const {merge} = require('webpack-merge')
const baseConfig = require('./webpack.base.config')
const devConfig = require('./webpack.dev.config')
const proConfig = require('./webpack.pro.config')

// 通过判断环境参数,决定将基础配置和生产环境配置 / 开发环境配置合并
let config = process.env.NODE_ENV === 'development' ? devConfig : proConfig
console.log(process.env.NODE_ENV)
module.exports = merge(baseConfig, config)
// webpack.pro.config.js 完整配置
const { CleanWebpackPlugin } = require('clean-webpack-plugin') 
module.exports = {
  plugins: [
    new CleanWebpackPlugin()
  ]
}

总结

在现在框架盛行的时代,可能很多人已经离不开框架,随着各种框架、自动化构建工具的越来越智能化,更多的细节被封装起来,我们越来越多的时间被业务开发所占据,我问自己一个问题,当某个时间,当我放下框架,我还能自己动手完成这些并不复杂的配置吗,这个问题让我警醒,在完成业务开发的闲暇时光,不能丢了看似繁琐,意义不大的基础的东西,毕竟,那些才是能够支撑我们走得更远的东西!

往期好文推荐

面试官:说说从输入 URL 到页面显示到底经历了什么,体现一下你的知识广度

面试官:作为前端,服务器相关了解多少?

面试官:HTTPS 采用的是对称加密还是非对称加密?具体说说其加密过程

面试官:说说 Cookie 和 Token 的区别?

面试官:网络安全了解多少,简单说说?(一)

面试官:网络安全了解多少,简单说说?(二)

面试官:网络安全了解多少,简单说说?(三)

面试官:网络安全了解多少,简单说说?(四)

面试官:网络安全了解多少,简单说说?(五)

面试官:网络安全了解多少,简单说说?(六)

面试官:网络安全了解多少,简单说说?(七)

面试官:网络安全了解多少,简单说说?(八)

浅尝 | 从 0 到 1 Vue 组件库封装

面试官:这么简单的正则表达式都不会?

Webpack 打包类库踩坑

面试官:你就只会 npm run build 吗?(Webpack 配置 Vue+Ts)

面试官:连VuePress都没搭过还说开发过组件库?(VuePress 搭建)

面试官: 连 Vue 视图更新都不会写?(Vue视图更新原理【一】)

面试官: 能不能手写 Vue 响应式?(Vue2 响应式原理【完整版】)

面试官:能不能手写 Vue3 响应式(Vue3 原理解析之响应系统的实现)

JS 优雅之道(JS 代码优化小 Tip)

面试官:你真的会用 SVG 吗? (SVG 应用实战)

面试官:说一下这个Loading动画实现思路 (CSS3 实现 Loading 动画)

JS 扫盲题 ( 面试题梳理系列 (一))

面试官:你确定你说的防抖不是节流吗?( 面试题梳理系列 (二))

面试官:除了 HTTP,你还用过什么通信协议?(Websocket 在数字孪生中的应用)

面试官:你真的理解 Event Loop 吗?( JS 事件循环 )

面试官:v-for 中 key 为什么不能用 index,从原理层面聊聊?

面试官:vue-router 的 hash 与 history 哪个模式会刷新页面?

面试官:说说你平时用过的自适应方案(数字孪生可视化自适应方案)

面试官:说一下如何优化过渡动画(数字孪生可视化过渡动画)

写在最后

博主接下来将持续更新好文,欢迎关注博主哟!! 如果文章对您有帮助麻烦亲点赞、收藏 + 关注和博主一起成长哟!!❤️❤️❤️