使用Webpack5搭建Vue3+Ts环境

1,294 阅读6分钟

前言

最近在复习webpack的知识,觉得光看不练是学不好webpack的,所以有了手动搭建一个Vue3+Ts运行环境的想法。废话不多说,直接开始进行搭建。

创建文件夹,并且进入该目录

生成package.json文件

如果你的目录名字是合法的,可以直接加上-y。这代表所有的选项都选择yes。

npm init

安装webpack,webpack-cli

这里的webpack和webpack-cli在开发环境需要,而在生成环境是不需要的。所以加上-D

npm install webpack webpack-cli -D

在package.json中创建脚本

我们可以直接在命令行通过npx webpack进行打包,但是我们也可以通过在package.json文件中,创建一个build脚本,这样就可以通过npm run build执行打包操作了。

image.png

创建webpack配置文件

默认情况下在根目录下创建webpack.config.js文件,即可对webpack进行配置。但是考虑到后面配置的命令可能会比较多。所以这里对webpack的配置文件进行了拆分。在根目录下创建一个webpack_config文件夹,在该文件夹下,创建三个文件:webpack.common.js(进行通用配置的文件)webpack.dev.js(进行开发环境配置的文件)webpack.prod.js(进行生产环境配置的文件)

image.png

因为默认情况下,webpack会去读取webpack.config.js文件的配置,而这里我们的并不是在改文件进行配置,所以我们需要指定配置文件的目录。我们直接在package.json文件中的脚本命令那里设置即可。

webpack.common.js文件进行配置如下

const path = require('path')

module.exports = {
  entry: './src/main.js',  // 设置打包的入口文件,这里不需要../。因为这里是相对于context的,而context的路径就是根目录。
  output: {
    path: path.resolve(__dirname, '../bundle'), // 这里需要../ ,因为这里不是相对于context。
    publicPath: '/', 配置打包后index.html引入资源的前缀
    filename: 'js/[name].[chunkhash:6].bundle.js'clean: true   // 在打包之前,先将打包的文件删除掉。
  }
}

处理css,less文件

安装css-loader进行css文件的处理,安装style-loader(将样式通过style标签插入到html中)

安装less-loader对less文件进行处理。

安装postcss-loader,postcss-preset-env(这个是一个插件),用于对css文件添加浏览器前缀

npm install css-loader style-loader less-loader postcss-loader postcss-preset-env -D

进行配置

// 在webpack.common.js中
module.exports = {
    ...
    module: {
        rules: [
          {
            test: /\.css$/, // 匹配css文件
            use: [
              "style-loader",
              {
                loader: "css-loader",
                options: {
                  importLoaders: 1, // css-loader前还有几个loader
                }, 
              },
              {
                loader: "postcss-loader", 
                options: {   
                  postcssOptions: {    // 对postcss的配置也可以单独抽离到一个文件中,这里就不抽取了。
                    plugins: ['postcss-preset-env'],
                  }
                },
              },
            ],
          },
          {
            test: /\.less$/,
            use: [
              'style-loader',
              {
                loader: 'css-loader',
                options: {
                  importLoaders: 2
                }
              },
              {
                loader: 'postcss-loader',
                options: {
                  postcssOptions: {
                    plugins: ['postcss-preset-env']
                  }
                }
              },
              'less-loader'
            ]
          }
        ],
      },

处理图片以及字体资源

在webpack5处理这些资源可以直接使用asset module type进行处理,不需要安装file-loader或者url-loader进行处理。

进行配置

// webpack.common.js
module.exports = {
    ...
    module: {
        rules: [
            {
                test: /\.(jpe?g|svg|png)$/,  // 匹配的资源
                type: 'asset',   // asset,结合了file-loader和url-loader的功能
                generator: {
                  filename: 'img/[name].[hash:6][ext]' // 生成的文件名
                },
                parser: {
                  dataUrlCondition: {
                    maxSize: 10 * 1024  // 当生成的图片小于10kb,则不会生成图片,会转成base64
                  }
                }
              },
              {
                test: /\.(tff|woff|ttf)$/,
                type: "asset",
                generator: {
                  filename: "fonts/[name].[hash:6][ext]",
                },
                parser: {
                  dataUrlCondition: {
                    maxSize: 8 * 1024,
                  },
                },
              },
        ]
    }
}

生成html文件

到目前为止,我们打包后的文件是没有html文件的。如果我们想要在打包后生成html文件,我们可以使用html-webpack-plugin帮助我们进行html文件的生成。该生成的html会自动帮助我们进行文件的引入。

安装html-webpack-plugin

npm install html-webpack-plugin -D

在使用该plugin时,我们可以为它指定一个html的模板,也可以让它自动为我们生成html文件

进行配置

// webpack.common.js
const HtmlWebpackPlugin = require('html-webpack-plugin')  // 导入该插件

module.exports = {
    ...
    plugins: [
        new HtmlWebpackPlugin() // 如果需要对该插件进行进一步的配置,可以自行查找资料
    ]
}

创建一个服务

在进行vue开发时,我们会执行npm run serve创建一个本地服务。在webpack中,如果想要创建一个本地服务,需要安装webpack-dev-server

npm install webpack-dev-server -D

在package.json文件中创建一个脚本

image.png

然后执行npm run serve即可开启一个本地服务。

创建了本地服务后,我们可以对本地服务进行一些配置。而这些配置是在开发是才会用到的,在打包时是不需要用到的,所以这里对之前的配置进行分离。

进行配置文件的分离

首先在执行脚本时,可以传入一个参数,这样我们就可以判断当前是要使用开发配置还是使用生产配置。

image.png

当我们的配置文件导出的是一个函数时,webpack会将我们传入的参数作为函数的参数传递给我们,我们就可以根据这个参数来决定使用哪些配置。

除了获取到配置模式,我们还需要将配置命令进行合并。可以使用webpack-merge插件来帮助我们完成配置的合并。

npm install webpack-merge -D
// webpack.common.js
const { merge } = require('webpack-merge') // 获取merge函数

const commonConfig = {} // 这个对象保存着之前的配置

module.exports = (env) => {
  // 判断当前的模式
  const mode = env.production ? 'production' : 'development'
  let config = null
  // 根据不同模式,导入不同配置
  if (mode === 'production') {
    config = require('./webpack.prod')
  } else {
    config = require('./webpack.dev')
  }
  // 返回合并后的配置文件
  return merge(commonConfig, config)
}

配置devServer

// webpack.dev.js
module.exports = {
    mode: 'development',
    devtool: 'cheap-module-source-map', // 设置source-map文件,便于开发代码调试
    devServer: {
        hot: true, // 开启模块热替换,默认就是开启的
        historyApiFallback: {  // 处理路由 history 模式刷新页面丢失
            rewrites: [
                {
                    from: /\.*/,    // 匹配所有的路径
                    to: '/index.html'  // 映射到index.html文件中
                }
            ]
        }
    
    }
}

处理js文件

在打包的时候,为了做浏览器的适配,我们需要对ES6+的js装换成ES5的代码。这个时候我们就可以使用babel来帮助我们装换。

安装babel-loader @babel/core @babel/preset-env

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

进行配置

因为对js代码的适配,只需要在打包的时候进行转换即可。在开发过程中,没有必要对代码进行转换,所以这里只在prod文件进行配置即可。

module.exports = {
  mode: 'production',
  module: {
    rules: [
      {
        test: /\.js$/,
        exclude: /node_modules/,   // 不处理node_modules下的js文件,这样就不会消耗打包时间
        use: {
          loader: 'babel-loader',
          options: {
            presets: ['@babel/preset-env']
          }
        }
      }
    ]
  }
}

处理ts文件

处理ts文件我们可以通过babel-loader和@babel/preset-typescript来处理,也可以通过ts-loader来处理。这里我采用开发时使用,ts-loader这样可以对一下ts错误进行检测打包时采用babel-loader,这样可以对转换后的js做一下兼容处理。

使用ts-loader是必须要有tsconfig.json文件,如果没有可以在终端使用tsc --init。如果报错,在全局安装typescript即可。

npm install @babel/preset-typescript ts-loader typescript -D

进行配置

开发环境下配置

// webpack.dev.js
module.exports = {
    ...
    module: {
        rules: [
          {
            test: /\.ts$/,
            exclude: /\.ts$/,
            use: {
              loader: 'ts-loader',
              options: {
                  appendTsSuffixTo: [/\.vue$/],  // 处理在vue文件中使用ts
                  transpileOnly: true,  // 关闭类型检测,这样可以减少编译时间。
              }
            }
          }
        ]
      }
    }

在上面的配置中,我们关闭了类型检测,以减少编译时间,我们可以将类型检测的职责交给另一个插件来帮助我们完成,这个插件会开启另一个线程来帮助我们进行类型检测。

安装fork-ts-checker-webpack-plugin插件

npm install fork-ts-checker-webpack-plugin -D

在上面的配置的基础上加上该插件的使用即可。

// webpack.dev.js
const ForkTsCheckerWebapckPlugin = require('fork-ts-checker-webpack-plugin')// 导入该插件

module.exports = {
    ...
    module: {
        rules: [
          {
            test: /\.ts$/,
            exclude: /node_modules/,
            use: {
              loader: 'ts-loader',
              options: {
                  appendTsSuffixTo: [/\.vue$/],  // 处理在vue文件中使用ts
                  transpileOnly: true,  // 关闭类型检测,这样可以减少编译时间。
              }
            }
          }
        ]
      }
   plugins: [
       new ForkTsCheckerWebpackPlugin()
   ] 
  }

生成环境下配置

// webpack.prod.js
module.exports = {
    ...
  module: {
    rules: [
      {
        test: /\.ts$/,
        use: {
          loader: 'babel-loader',
          options: {
            presets: [
              '@babel/preset-env',
              ['@babel/preset-typescript', {
                // 这个配置是为了处理.vue文件解析后的ts文件
                allExtensions: true
              }]
            ]
          }
        }
      }
    ]
  }
}

处理.vue文件

处理 .vue文件 需要安装 vue-loader和@vue/compiler-sfc。 因为当前处理的是vue3的文件,而vue3还没有作为默认版本,所以需要安装vue-loader@next,当vue3成为默认版本的时候就直接安装即可。

npm install @vue/compiler-sfc vue-loader@next -D**

因为不论是在开发环境还是生成环境,都需要对 .vue文件 进行处理。所以这里将.vue文件的处理配置放在了webpack.common.js文件中

进行配置

const { VueLoaderPlugin } = require('vue-loader')  // 导入VueLoaderPlugin
module.exports = {
    ...
    module: {
        rules: [
            {
                test: /\.vue$/,
                exclude: /node_modules/,
                loader: 'vue-loader'
            }
        ]
    },
    plugins: [
        new VueLoaderPlugin()  // 这里要使用这个插件
    ]
}

打包后,运行时会发现会有如下警告

image.png

这个警告的意思是,vue强烈推荐我们自己定义__VUE_OPTION_API_,VUE_PROD_DEVTOOLS 这两个变量,这两个变量一个是决定要不要使用optionsAPI,一个是决定要不要启用Devtools插件。我们可以根据自己的情况进行定义。

在webpack中如何定义全局变量呢,我们可以通过webpack内置的DefinePlugin插件来进行定义。

// webpack.common.js
const { DefinePlugin } = require('webpack')

module.exports = {
    ...
    plugins:[
        new DefinePlugin({
            __VUE__OPTION_API__: false,
            __VUE_PROD__DEVTOOLS: true
        })
    ]
}

进行完上面的全局变量的定义,再次打开就会发现没有上面的警告了。

总结

通过上面的基本配置,我们就可以运行vue3和ts的项目了。接下来还需要对该项目进行一些优化,将在之后进行处理。