头图

【基础篇】webpack5搭建Vue3+Typescript 基础开发环境

justX

image-20210729110919542

前言

最近对公司远古项目进行升级整理,发现webpack5性能上有了很大的提升,加上对vue3的使用,特地尝试从零开始搭建一个vue3的开发环境,不使用官方的脚手架主要是为了加深对这套技术的理解

仓库地址

准备工作

第一步:创建工程目录并初始化

mkdir wp5-vue3
cd wp5-vue3
npm init -y

第二步:安装webpack

npm i webpack webpack-cli -D
这里没有选择全局安装,大家可以根据自己的实际情况进行选择

第三步:创建入口目录 src 及入口文件 index.js

mkdir src
touch src/index.js
随便写点内容
// index.js
console.log('hello webpack5')

用过webpack的应该都知道四个核心概念

  • 入口(entry)
  • 输出(output)
  • loader
  • 插件(plugins)

webpack 默认entry 就是根目录下 src/index.js

在输出前通过各种loaderplugins 对文件进行处理

最终输出到 output 指定的文件夹 默认是根目录下 dist 文件夹

所以到这里基本就是一个webpack基础的样子 通过命令行输入 webpack 则可以实现简单的打包

image-20210728161314821

image-20210728161341533

第四步:声明配置文件

虽然官方声称 从 webpack v4.0.0 开始,可以不用引入一个配置文件。然而还是需要进行自定义配置,修改一些默认配置或搭配一些loader和plugins对项目进行处理,所以我们在项目根目录声明webpack.config.js,习惯性命名 文件名没有强制规定,通过 --config 指定配置文件路径
/*
 * @Description: webpack.config.js
 * @Author: justX
 * @LastEditors: justX
 * @Date: 2021-07-28 16:15:10
 * @LastEditTime: 2021-07-28 16:20:59
 * @FilePath: /wp5-vue3/webpack.config.js
 */
const path = require('path');

module.exports = {
    mode: 'development',
    entry: './src/index.js',
    output: {
        filename: '[name].js',
        path: path.resolve(__dirname, 'dist')
    }
}

image-20210728162227132

修改package.json 新增 scripts 字段
"scripts": {
  "build": "webpack --config 配置文件路径"
}

基础配置

完成基础配置先别着急这开发,我们丰富一下配置让整个脚手架更好用,像日常开发中 html文件自动插入打包后的文件、本地服务实时预览、ES6+语法转换 以及 vue/less/sass等的使用, 接下来我们就逐个完善

创建html模板文件

通过webpack 插件 html-webpack-plugin 实现将打包后的js 自动插入到html模板

​ 1.安装依赖

npm i html-webpack-plugin -D

​ 2.修改配置

plugins: [
  new HtmlWebpackPlugin({
    template: './index.html',
    filename: 'index.html',
    title: 'webpack5-vue3'
  })
]
然后 npm run build 查看 dist 目录下的 index.html,打包后的文件已经自动引入,我们在浏览器查看该文件,页面正常显示 控制台也正常输出, 但是每次修改都要手动刷新,这绝对是我们不能忍受的! 所以下面就来解决这个问题

本地服务 DevServer

通过webpack 插件 webpack-dev-server 实现本地开发服务器

​ 1.安装依赖

npm i webpack-dev-server -D

​ 2.修改配置

module.exports = {
  //...
  devServer: {
    contentBase: path.join(__dirname, 'dist'),
    compress: true,
    port: 9000,
  },
};

​ 3. 修改 package.json 新增scripts,通过CLI 调用 webpack-dev-server

 "scripts": {
    "serve": "npx webpack serve",
    "build": "npx webpack --config webpack.config.js"
  }
  • 注意:webpack5启动开发服务器与之前版本有所区别 从 webpack-dev-server 改成了 webpack serve
然后 npm run serve 可以看到终端输出了本地服务的地址 我们点击访问

image-20210728170007920

现在我们修改一下 index.js 的代码内容 看看是不是会自动刷新
// ES6 箭头函数
let arrowFn = () => {
  console.log('es6: arrow function')
};
arrowFn();

// ES7 数组includes
console.log('es7:', [1,2,3].includes(1))

// ES8 对象 entries
let obj = {a: 1, b: 2, c: 3};
Object.entries(obj).forEach(([key, value]) =>{
  console.log('es8', key + ": " + value); // 输出a: 1, b: 2, c: 3
})
但是当我们将上面的代码运行再ie这些老版本浏览器上 会发现js报错 无法运行,那么接下来我们就要将 ECMAScript 2015+ 代码转换为 JavaScript 向后兼容版本的代码

ES6+语法转换

安装babel核心 、对应loader 以及预置环境

​ 1.安装依赖

npm i @babel/core babel-loader @babel/preset-env -D

​ 2.修改配置

module.exports = {
// ...
  module: {
    rules: [
      {
        test: /\.js$/,
        use: {
          loader: 'babel-loader',
          options: {
            presets: ['@babel/preset-env']
          }
        }
      }
    ]
  }
}
关于babel的配置 我们可以写在 options 里 也可以单独一个文件参考文档

样式处理

项目使用的预处理器是less

相关依赖 style-loader css-loader less less-loader

​ 1.安装依赖

npm i  style-loader css-loader less less-loader -D

​ 2.修改配置

module.exports = {
// ...
  module: {
    rules: [
      // ...
      {
        test: /\.css$/,
        use: [
          {
            loader: 'style-loader',
            options: {}
          },
          {
            loader: 'css-loader',
            options: {}
          }
        ]
      },
      {
        test: /\.less$/,
        use: [
          {
            loader: 'style-loader',
            options: {}
          },
          {
            loader: 'css-loader',
            options: {}
          },
          {
            loader: 'less-loader',
            options: {}
          }
        ]
      }
    ]
  }
}

tips:多loader加载顺序 是从下到上 从左到右,所以这里的顺序一定不能错哦~

至此我们已经处理完前端三大件 HTMl JS CSS,完成了一个网页组成的基本条件,但只是这些远远不够,接下来我们继续完善 静态资源/vue3/ts/代码规范/多环境 等配置

静态资源(图片,字体,音频等)

资源模块(asset module)是一种模块类型,它允许使用资源文件(字体,图标等)而无需配置额外 loader。

在 webpack 5 之前,通常使用:

资源模块类型(asset module type),通过添加 4 种新的模块类型,来替换所有这些 loader:

  • asset/resource 发送一个单独的文件并导出 URL。之前通过使用 file-loader 实现。
  • asset/inline 导出一个资源的 data URI。之前通过使用 url-loader 实现。
  • asset/source 导出资源的源代码。之前通过使用 raw-loader 实现。
  • asset 在导出一个 data URI 和发送一个单独的文件之间自动选择。之前通过使用 url-loader,并且配置资源体积限制实现。

​ 1.自定义输出文件名的两种方式

// 默认情况下,asset/resource 模块以 [hash][ext][query] 文件名发送到输出目录。
// 有两种方式
// 第一种 在output里配置 assetModuleFilename
module.exports = {
    // ...
  output: {
    // ...
    assetModuleFilename: 'images/[hash][ext][query]'
  }
}
// 第二种 在指定资源 generator 里配置 filename
module.exports = {
  module: {
    rules: [
      {
       test: /\.html/,
          type: 'asset/resource',
        generator: {
          filename: 'static/[hash][ext][query]'
        }
        }
    ]
  }
}
Rule.generator.filenameoutput.assetModuleFilename相同,并且仅适用于 assetasset/resource 模块类型

​ 2.修改配置

module.exports = {
  module: {
    rules: [
             {
               test: /\.(png|jpe?g|gif|svg)(\?.*)?$/,
          type: 'asset',
          parser: {
            dataUrlCondition: {
              maxSize: 10 * 1024 // 10kb  指定大小 小于该值则使用inline模式
            }
          }
        },
        {
          test: /\.(mp4|webm|ogg|mp3|wav|flac|aac)(\?.*)?$/,
          type: 'asset',
          parser: {
            dataUrlCondition: {
              maxSize: 10 * 1024 // 10kb  指定大小
            }
          }
        },
        {
          test: /\.(woff2?|eot|ttf|otf)(\?.*)?$/,
          type: 'asset',
          parser: {
            dataUrlCondition: {
              maxSize: 10 * 1024 // 10kb  指定大小
            }
          }
        }
    ]
  }
}
  • 效果图

    可以正常显示图片了 音频字体也是一样的就不一一展示了

image-20210805154759986

vue3 相关配置

核心依赖/插件/loader

npm install -S vue@next vue-router@next vuex@next vue-loader@next @vue/compiler-sfc
  • vue/vue-router/vuex 三大件 对应3.*版本的
  • VueLoaderPlugin 的导入方式改变了
  • vue-loader@next 当前需要自行指定版本(配置如下)
  • 新增了 @vue/compiler-sfc 替换原来的 vue-template-compiler
  • 相关的Webpack 配置
const { VueLoaderPlugin } = require('vue-loader')
module.exports = {
  ...
  module: {
    ...
    rules: [
      {
        test: /\.vue$/,
        use: [
          {
            loader: 'vue-loader'
          }
        ]
      }
    ]
  },
  plugins: [
    ...
    new VueLoaderPlugin()
  ]
  ...
}
至此可以实现vue3的基础支持

扩展配置

Typescript

​ vue3更好的支持了ts, 所以这里我们在项目中加入ts支持

有两种方案:

 1. npm i typescript ts-loader -D
 2. babel7 版本 增加了 @babel/preset-typescript` 预设
  • 关于两种方式的区别

    可参考知乎文章 [为什么说用 babel 编译 typescript 是更好的选择](https://zhuanlan.zhihu.com/p/376867546),自行进行选择
    

之前一直用的是tsc 配置,在这里尝试一下babel7,配置如下

// 官方相关链接 
// https://babeljs.io/docs/en/babel-preset-env#usebuiltins
// https://babeljs.io/docs/en/babel-preset-typescript
// 相关依赖
"babel-loader": "^8.2.2",
"@babel/core": "^7.14.8",
"core-js": "^3.17.2",
"regenerator-runtime": "^0.13.9",
"@babel/preset-env": "^7.14.8",
"@babel/preset-typescript": "^7.15.0",
"@babel/plugin-proposal-class-properties": "^7.14.5",


// babel.config.js 配置
module.exports = function (api) {
  api.cache(true)

  const presets = [
    [
      '@babel/preset-env',
      {
        targets: 'last 1 version,> 1%,not dead',
        corejs: 3,
        useBuiltIns: 'usage' // 按需加载 减小打包体积 并自动引入core-js 和 regenerator-runtime
      }
    ],
    [
      '@babel/preset-typescript', // 引用Typescript插件
      {
        allExtensions: true // 支持所有文件扩展名,否则在vue文件中使用ts会报错
      }
    ]
  ]
  const plugins = [
    '@babel/proposal-class-properties'
  ]

  return {
    presets,
    plugins
  }
}

src 文件夹下添加 shims-vue.d.ts 文件,解决 vue 类型报错

// shims-vue.d.ts
declare module '*.vue' {
  import type { DefineComponent } from 'vue'
  const component: DefineComponent<{}, {}, any>
  export default component
}

Eslint

在团队开发中,合理的代码规范有利于代码维护及相互协作,但每个团对都会有自己约定而成的规范,所以这里没有唯一标准, 此处选择初始化推荐规则
  • 初始化配置文件 【操作界面如下图】
npm install eslint eslint-webpack-plugin -D
// 初始化配置文件 【操作界面如下图】
> eslint --init                      
✔ How would you like to use ESLint? · problems
✔ What type of modules does your project use? · esm
✔ Which framework does your project use? · vue
✔ Does your project use TypeScript? · No / Yes
✔ Where does your code run? · browser✔ What format do you want your config file to be in? · JavaScript
The config that you've selected requires the following dependencies:

eslint-plugin-vue@latest @typescript-eslint/eslint-plugin@latest @typescript-eslint/parser@latest
✔ Would you like to install them now with npm? · No / Yes
Installing eslint-plugin-vue@latest, @typescript-eslint/eslint-plugin@latest, @typescript-eslint/parser@latest

image-20210906102415855

  • 自定义规则 可在 .eslintrc 配置文件中配置
// 自定义规则 可在 .eslintrc 配置文件中配置
"rules": {
  // override default options
  "comma-dangle": ["error", "always"],
  "indent": ["error", 2],
  "no-cond-assign": ["error", "always"],

  // disable now, but enable in the future
  "one-var": "off", // ["error", "never"]

  // disable
  "init-declarations": "off",
  "no-console": "off",
  "no-inline-comments": "off",
}
  • 引入共享配置

    需要注意 第三方共享配置自定义 需要按照第三方规则进行修改
// 或者在extends 里引入共享配置  standard/airbnb/prettier  需要安装对应依赖
// 例如: npm install --save-dev eslint-config-standard eslint-plugin-promise eslint-plugin-import eslint-plugin-node
// 相同规则时 后面覆盖前面
"extends": [
  "eslint:recommended",
  "standard"
  "plugin:vue/essential",
  "plugin:@typescript-eslint/recommended"
]
  • eslint 自动修复
// eslint 自动修复 添加webpack 脚本 具体参数查看官方文档
"scripts": {
  "lint": "eslint --fix --ext .ts,.js,.vue src"
}

多环境

我们项目一般会分为生产和测试两个环境,对应的webpack配置也一定是不一样的,

首先,webpack自身配置 mode 就提供三种模式 ‘’ (空模式) development(测试模式) production (生产模式),具体的目的可查看: 指定mode

那么我们依据不同模式区分出三个文件

基础通用配置:webpack.base.config.js

测试模式配置:webpack.base.config.js

生产模式配置:webpack.base.config.js

  • 具体配置就不写出来了,大家可以自行思考一下怎样工程化这些配置,哪些是基础配置,哪些是对应模式特有的配置,根据每个plugin loader 的官方文档描述,进行对应模式的配置
  • 配置对应script

    "scripts": {
      "serve": "npx webpack serve --config ./config/webpack.dev.config.js --progress ",
      "build": "webpack --config ./config/webpack.prod.config.js",
    },

遇到的问题

  • 使用<router-view/> 组件的时候发生下面的报错,

    [Vue warn]: Component provided template option but runtime compilation is not supported in this build of Vue. Configure your bundler to alias "vue" to "vue/dist/vue.esm-bundler.js"

    大概意思是: 组件提供模板选项,但是在Vue的这个构建中不支持运行时编译,配置你的bundler别名 vue: vue/dist/vue.esm-bundler.js

    在vue-cli脚手架其实有着一段设置 不知道大家使用的时候有没有注意到

    具体参考 官方文档

    配置vue别名

    resolve: {
      alias: {
          'vue': 'vue/dist/vue.esm-bundler.js'
      }
    }

写在最后

到此《webpack5+vue3+typescript》的基础搭建算告一段落, 此文章目的仅为搭建一个基础的vue3开发环境提供一个基础思路,实际开发的细节并不止于此,比如webpack细节配置以及开发后期都会遇到的构建速度优化问题等,特别是关于构建优化,在webpack5上相较于webpack4变动还是比较大的,特别是在项目越来越大,这些优化就显得格外明显,后面有机会再写一篇关于webpack5优化的文章和他家一起学习探讨,文笔有限,若文中有错误还望各位指出改正!

最后贴心小tips: 大家在学习新知识的时候可以参考写得好的博文,不理解的地方一定要

看文档!

看文档!

看文档!

webpack

vue3

babel

image-20210906142107049

阅读 245

书写是为了更好的思考,文字记录了我的成长

0 声望
0 粉丝
0 条评论
你知道吗?

书写是为了更好的思考,文字记录了我的成长

0 声望
0 粉丝
宣传栏