从零开始搭建一个前端项目(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

相关推荐
我要洋人死21 分钟前
导航栏及下拉菜单的实现
前端·css·css3
科技探秘人33 分钟前
Chrome与火狐哪个浏览器的隐私追踪功能更好
前端·chrome
科技探秘人33 分钟前
Chrome与傲游浏览器性能与功能的深度对比
前端·chrome
JerryXZR39 分钟前
前端开发中ES6的技术细节二
前端·javascript·es6
七星静香41 分钟前
laravel chunkById 分块查询 使用时的问题
java·前端·laravel
q24985969343 分钟前
前端预览word、excel、ppt
前端·word·excel
小华同学ai1 小时前
wflow-web:开源啦 ,高仿钉钉、飞书、企业微信的审批流程设计器,轻松打造属于你的工作流设计器
前端·钉钉·飞书
Gavin_9151 小时前
【JavaScript】模块化开发
前端·javascript·vue.js
懒大王爱吃狼2 小时前
Python教程:python枚举类定义和使用
开发语言·前端·javascript·python·python基础·python编程·python书籍
逐·風6 小时前
unity关于自定义渲染、内存管理、性能调优、复杂物理模拟、并行计算以及插件开发
前端·unity·c#