从零开始搭建一个前端项目(webpack+ts+vue)

前言

不知道什么时候,搭建一个前端项目,慢慢成为了我的执念,总感觉不搭建一个,总是缺点什么(虽然日常根本用不到,因为公司都是用那些集成脚手架,从vue-cli再到vite),正是抱着这种心态,我写了这篇文章(从零开始搭建(基于webpack5+),最后部署在github)。

目标

满足日常的开发环境(dev)以及本地预览(preview),和发布部署(github pages)。

为了这个目标,我们需要做什么呢?我是拆分成两个目标

需处理的文件

  1. scss/css文件。
  2. js/json/ts/tsx文件。
  3. vue单文件。
  4. 图片和字体以及其他静态资源。

需要支持的功能

  1. 本地开发文件热更新。
  2. 多环境/设置环境变量。
  • 开发环境
  • 生产环境
  • 本地预览环境
  1. 分包构建时,不同的资源放入不同的文件夹。
  2. 第三方包打包时,分割成独立的文件。

开始冲!!!

代码实现

1. 创建文件夹

cmd 复制代码
mkdir project

2. 生成package.json

cmd 复制代码
npm init -y

3. 安装webpackwebpack-cliwebpack-dev-server

cmd 复制代码
npm install --save-dev webpack webpack-cli webpack-dev-server

4. 现在项目已经搭建好了我们现在来分析下需处理的文件。

  • scss/css文件。
  • js/json/ts/tsx文件。
  • vue单文件。
  • 图片和字体以及其他静态资源。

对于这些文件的处理,其实webpack都已经提供了相应的loader来处理。

  • sass-loadercss-loaderstyle-loader可以来处理sass/css文件。
  • jsjsonwebpack天然就支持,我们仅仅需要bebal-loader 来转化我们的js(es6+),对于ts/tsx我们可以使用@babel/preset-typescript
  • 至于vue单文件,我们可以使用vue官方提供的vue-loader来处理。
  • 最后在说静态资源,我们可以使用webpack的资源模块(asset module)来处理。

下面来配置我们webpack.common.js

webpack.common.js 复制代码
const { VueLoaderPlugin } = require("vue-loader")
const { loader } = MiniCssExtractPlugin
module.exports = (env) => {
  return {
    entry: "./src/index.ts",
    plugins: [
      new VueLoaderPlugin()
    ],
    resolve: {
      extensions: [".vue", ".tsx", ".ts", ".js"],
    },
    module: {
      rules: [
        {
          test: /\.vue$/i,
          use: ["vue-loader"],
        },
        {
          test: /\.s[ac]ss$/i,
          use: [
            env.mode === "development" ? "style-loader" : loader,
            "css-loader",
            "sass-loader",
          ],
        },
        {
          test: /\.css$/i,
          use: [
            env.mode === "development" ? "style-loader" : loader,
            "css-loader",
            "sass-loader",
          ],
        },
        {
          test: /\.(ts|tsx)?$/,
          exclude: /(node_modules)/,
          loader: "babel-loader",
          options: {
            presets: [
              "@babel/preset-env",
              [
                "@babel/preset-typescript",
                {
                  allExtensions: true,
                },
              ],
            ],
          },
        },
        // 图片
        {
          test: /\.(png|svg|jpg|jpeg|gif)$/i,
          type: "asset/resource"
        },
        // 字体
        {
          test: /\.(woff|woff2|eot|ttf|otf)$/i,
          type: "asset/resource"
        },
      ],
    },
  }
}

针对ts还需要在项目根目录创建tsconfig.json

tsconfig.json 复制代码
{
    "compilerOptions": {
        "outDir": "./docs/",
        "noImplicitAny": true,
        "module": "ESNext",
        "target": "ES2020",
        "jsx": "react",
        "allowJs": true,
        "moduleResolution": "node",
        "allowSyntheticDefaultImports": true,
        "esModuleInterop": true,
        "baseUrl": "./",
        "paths": {
            "@/*": [
                "src/*"
            ]
        }
    },
    "include": [
        "src/**/*",
    ],
    "exclude": [
        "node_modules"
    ]
}

自此我们的第一个目标已经完成,继续冲!!!

需要支持的功能

  1. 本地开发文件热更新。
  2. 多环境/设置环境变量。
  • 开发环境
  • 生产环境
  • 本地预览环境
  1. 分包构建时,不同的资源放入不同的文件夹。
  2. 第三方包打包时,分割成独立的文件。

1. 本地开发文件热更新

这个我们可以使用webpack提供的webpack-dev-server来完成。 我们需要先配置webpack.dev.js

webpack-dev.js 复制代码
const { merge } = require("webpack-merge")
const webpack = require("webpack")
const common = require("./webpack.common.js")
module.exports = merge(common({ mode: "development" }), {
  mode: "development",
  devServer: {
    static: "./docs"
  }
})

然后配置package.jsonscript命令

cmd 复制代码
    "start": "webpack serve --open --config webpack.dev.js",

我先来解释下上面的那个配置项,意思是,它会在把打包的文件,放到docs文件夹下(先说下这个为啥不用默认的dist文件夹,因为github page部署静态资源,它需要这个资源放在docs文件夹才可以,后面部署在详说 ),这个文件夹是不可见的(存在内存中),并且默认部署在localhost:8080

2. 多环境/设置环境变量

其实所谓的多环境,其实都是差不多的,都是把资源打包到一个文件夹,无非是生产环境的代码更小。 而对于环境变量的配置,我们可以使用DefinePlugin来设置,这是官网对这个插件的描述:

下面我们来设置环境变量

开发环境

webpack.dev.js 复制代码
const { merge } = require("webpack-merge")
const webpack = require("webpack")
const common = require("./webpack.common.js")
module.exports = merge(common({ mode: "development" }), {
  mode: "development",
  devtool: "inline-source-map",
  devServer: {
    static: "./docs",
    // 忽略编译错误
    client: {
      overlay: false,
    },
  },
  plugins: [
    // 定义环境变量
    new webpack.DefinePlugin({
      "process.env": {
        NODE_ENV: JSON.stringify("development"),
        serverUrl: JSON.stringify("dev"),
        base: JSON.stringify("/base-dev"),
      },
    }),
  ],
})

生产环境

webpack.prod.js 复制代码
const webpack = require("webpack")
const { merge } = require("webpack-merge")
const common = require("./webpack.common.js")
module.exports = merge(common({ mode: "production" }), {
  mode: "production",
  plugins: [
    new webpack.DefinePlugin({
      "process.env": {
        NODE_ENV: JSON.stringify("production"),
        serverUrl: JSON.stringify("pro"),
        base: JSON.stringify("/base-pro"),
      },
    }),
  ],
})

本地预览环境

这里我想的是本地预览环境,其实就是我们本地提供一个node服务,然后提供对docs这些静态资源的访问,所以思路就是:我们在提供node服务前,只要先行执行构建命令npm run build就行。这里我们使用express来搭建服务。

cmd 复制代码
npm install --save-dev express open

open是一个打开链接/应用的插件,这里我们利用它打开chrome浏览器

server.js 复制代码
const express = require('express')
const app = express()
const port = 3000
app.use(express.static('docs'))
app.listen(port, () => {
    import('open').then(res => {
        res.default(` 本机的Ip:${port}`, { app: { name: 'chrome' } })
    })
})

然后修改package.json文件

package.json 复制代码
  "scripts": {
    "preview": "npm run build && node server.js"
  }

这样执行命令,我们就可以浏览器看到我们的项目了。

3. 分包构建时,不同的资源放入不同的文件夹

首先我们来分析下,我们最终打包生成的资源,无非就几种,js、css、静态资源(图片和字体),所以我们只需要针对不同的资源,做不同的配置即可。 在webpack.common.js进行如下配置

webpack.commom.js 复制代码
const path = require("path")
const MiniCssExtractPlugin = require("mini-css-extract-plugin")
const { loader } = MiniCssExtractPlugin
module.exports = (env) => {
  return {
    entry: "./src/index.ts",
    output: {
    // 把js文件打包docs/js
      filename: `js/[name].[hash].js`,
      path: path.resolve(__dirname, "docs"),
      clean: true,
    },
    plugins: [
    // 把css文件打包docs/css
      new MiniCssExtractPlugin({
        filename: "css/[name].[hash].css",
      }),
    ],
    module: {
      rules: [
        // 把图片打包到docs/assets
        {
          test: /\.(png|svg|jpg|jpeg|gif)$/i,
          type: "asset/resource",
          generator: {
            publicPath: "assets/",
            outputPath: "assets/",
          },
        },
        // // 把字体打包到docs/assets
        {
          test: /\.(woff|woff2|eot|ttf|otf)$/i,
          type: "asset/resource",
          generator: {
            publicPath: "assets/",
            outputPath: "assets/",
          },
        },
      ],
    },
  }
}

最后会生成如下目录结构:

4. 第三方包打包时,分割成独立的文件

我们可以通过配置optimization.splitChunks,来分割文件

webpack.common.js 复制代码
module.exports = (env) => {
return {
    optimization: {
      runtimeChunk: "single",
      splitChunks: {
        cacheGroups: {
          vendors:
            env.mode === "development"
              ? {}
              : {
                chunks: "all",
                test: /[\\/]node_modules[\\/]/,
                name (module) {
                  if (module.context.includes("node_modules")) {
                    const packageName = module.context.match(
                      /[\\/]node_modules[\\/](.*?)([\\/]|$)/
                    )[1]
                    return `${packageName.replace("@", "")}`
                  }
                },
              },
        },
      }
    }
} 
}

至此我们的目标就完成了,下面我们说下怎么部署到github

部署

大家都知道github本身是支持部署静态网站的,GitHub Pages,通过在这里配置,我们就可以有自己的静态网站。配置如下图:

第三步,可以看到这里指定资源是支持两种的root/docs,我们选择docs,这就是为啥,我们一开构建打包的时候,没有选择dist文件夹而是使用docs,这样设置之后,后面每次该分支上传代码,都会自动构建和部署(可以查看action)。

总结

至此我们的开发和部署目标就完成了,这个项目目前,本地开发编译有点慢,后续我再优化下,这是我的项目地址,大家有兴趣,可以自己clone下来 本地玩玩,也可以部署到自己的github

相关推荐
崔庆才丨静觅13 小时前
hCaptcha 验证码图像识别 API 对接教程
前端
passerby606114 小时前
完成前端时间处理的另一块版图
前端·github·web components
掘了14 小时前
「2025 年终总结」在所有失去的人中,我最怀念我自己
前端·后端·年终总结
崔庆才丨静觅14 小时前
实用免费的 Short URL 短链接 API 对接说明
前端
崔庆才丨静觅14 小时前
5分钟快速搭建 AI 平台并用它赚钱!
前端
崔庆才丨静觅15 小时前
比官方便宜一半以上!Midjourney API 申请及使用
前端
Moment15 小时前
富文本编辑器在 AI 时代为什么这么受欢迎
前端·javascript·后端
崔庆才丨静觅15 小时前
刷屏全网的“nano-banana”API接入指南!0.1元/张量产高清创意图,开发者必藏
前端
剪刀石头布啊15 小时前
jwt介绍
前端
爱敲代码的小鱼15 小时前
AJAX(异步交互的技术来实现从服务端中获取数据):
前端·javascript·ajax