使用 Webpack5 从 0 到 1 构建 Vue3 项目 + ts

基础构建

初始化项目结构

原则:尽量跟vue-cli构建项目,尽量保持一致

(1)创建 package.json

csharp 复制代码
npm init -y

(2)创建 tsconfig.json --- 若项目需要ts

csharp 复制代码
tsc --init

(3)如果没有 tsc,则执行下方命令

npm install typescript -g

此时文件结构如下:

安装webpack相关

(1)安装webpack

js 复制代码
yarn add webpack

(2)安装webpack-cli

js 复制代码
yarn add webpack-cli 

(3)安装启动服务

js 复制代码
yarn add webpack-dev-server

(4)安装html模板

js 复制代码
yarn add html-webpack-plugin 

(5)手动新建 webpack 配置文件 ------ webpack.config.js

初步编写webpack.config.js

(1)设置入口文件及出口文件

js 复制代码
// 增加代码智能提示
const { Configuration } = require('webpack')
const path = require('path')
/**
 * @type { Configuration } // 使用注解的方式,增加代码智能提示
 */
const config = {
    // 入口文件
    entry: './src/main.ts',
    // 出口文件
    output: {
        filename: "[hash].js",
        path: path.resolve(__dirname, 'dist')
    },
}
module.exports = config

此时需要手动构建项目结构,即创建src文件夹,及main.ts文件

(2) 指定 html 模板位置

js 复制代码
// 增加代码智能提示
const { Configuration } = require('webpack')
const path = require('path')
const htmlWebpackPlugin = require('html-webpack-plugin')
/**
 * @type { Configuration } // 使用注解的方式,增加代码智能提示
 */
const config = {
    // 入口文件
    entry: './src/main.ts',
    // 出口文件
    output: {
        filename: "[hash].js",
        path: path.resolve(__dirname, 'dist')
    },
    plugins: [
        new htmlWebpackPlugin({
            // 指定 html 模板位置
            template: "./public/index.html"
        }),
    ],
}
module.exports = config

此时需要手动构建项目结构,即创建public文件夹,及index.html文件

配置 运行/打包 命令

package.json 中,配置下面两条命令:

js 复制代码
"scripts": {
    "test": "echo \"Error: no test specified\" && exit 1",
    "dev": "webpack-dev-server",
    "build": "webpack"
}
js 复制代码
 "scripts": {
    "build": "webpack --mode=production --node-env=production",
    "build:dev": "webpack --mode=development",
    "build:prod": "webpack --mode=production --node-env=production",
    "dev": "webpack-dev-server",
  }

main.ts 中,随便写点内容,比如 const aar = 123;

(1)执行打包命令

js 复制代码
 npm run build /  yarn build

出现下方报错,告诉我们没指定 mode

webpack.config.js中指定mode

如果指定为开发环境,那么打包出来的代码,不会被压缩。

js 复制代码
// 增加代码智能提示
const { Configuration } = require('webpack')
const path = require('path')
const htmlWebpackPlugin = require('html-webpack-plugin')
/**
 * @type { Configuration } // 使用注解的方式,增加代码智能提示
 */
const config = {
    mode: "development",
    // 入口文件
    entry: './src/main.ts',
    // 出口文件
    output: {
        filename: "[hash].js",
        path: path.resolve(__dirname, 'dist')
    },
    plugins: [
        new htmlWebpackPlugin({
            // 指定 html 模板位置
            template: "./public/index.html"
        }),
    ],
}
module.exports = config

再执行一遍打包命令,顺利输出下方的文件,打包成功

(2)执行运行命令

js 复制代码
npm run dev / yarn dev

可以看出默认端口为 8080

可以通过devServer属性自行设置端口

js 复制代码
devServer: {
    open: true,
    host: "localhost",
    port: 3000
}

webpack.config.js完整版如下

js 复制代码
// 增加代码智能提示
const { Configuration } = require('webpack')
const path = require('path')
const htmlWebpackPlugin = require('html-webpack-plugin')
/**
 * @type { Configuration } // 使用注解的方式,增加代码智能提示
 */

const config = {
    mode: "development",
    // 入口文件
    entry: './src/main.ts',
    // 出口文件
    output: {
        filename: "[hash].js",
        path: path.resolve(__dirname, 'dist')
    },
    devServer: {
        open: true,
        host: "localhost",
        port: 3000
    },
    plugins: [
        new htmlWebpackPlugin({
            // 指定 html 模板位置
            template: "./public/index.html"
        }),
    ],
}
module.exports = config

其他webpack常用配置/插件

安装typescript及其loader

安装 typescript loader 协助 webpack 处理 ts

ts-loader是webpack的一个插件,通过TypeScript编译器(tsc)来处理TypeScript文件,并转换为JavaScript文件。

安装typescript

js 复制代码
yarn add typescript

安装 typescript loader

js 复制代码
yarn add ts-loader

webpack.config.js 中,补充配置

js 复制代码
// 增加代码智能提示
const { Configuration } = require('webpack')
const path = require('path')
const htmlWebpackPlugin = require('html-webpack-plugin')
/**
 * @type { Configuration } // 使用注解的方式,增加代码智能提示
 */

// console.log('process.env.NODE_ENV', process.env.NODE_ENV)
const config = {
    mode: "development",
    // 入口文件
    entry: './src/main.ts',
    // 出口文件
    output: {
        filename: "[hash].js",
        path: path.resolve(__dirname, 'dist')
    },
    devServer: {
        open: true,
        host: "localhost",
        port: 3000
    },
    plugins: [
        new htmlWebpackPlugin({
            // 指定 html 模板位置
            template: "./public/index.html"
        }),
    ],
    module: {
        rules: [
            {
                test: /\.ts$/, // 解析 ts
                loader: "ts-loader",
                exclude: /node_modules/
            }
        ]
    }
}
module.exports = config

此时可在main.ts文件中,写入ts语法,浏览器可以识别

js 复制代码
// 数值类型
let num: number;
num = 100
// num="刘亦菲"
num = 3.14

console.log(num);

删除上次打包文件的插件

随着打包次数的不断增多,打包文件也会越来越多

我们需要安装一个插件,在每次打包的时候,清空一下 dist 文件夹

(1)安装

js 复制代码
yarn add clean-webpack-plugin 

(2)在 webpack.config.js 中,补充配置

js 复制代码
// 增加代码智能提示
const { Configuration } = require('webpack')
const path = require('path')
const htmlWebpackPlugin = require('html-webpack-plugin')
const { CleanWebpackPlugin } = require('clean-webpack-plugin')
/**
 * @type { Configuration } // 使用注解的方式,增加代码智能提示
 */

const config = {
    mode: "development",
    // 入口文件
    entry: './src/main.ts',
    // 出口文件
    output: {
        filename: "[hash].js",
        path: path.resolve(__dirname, 'dist')
    },
    devServer: {
        open: true,
        host: "localhost",
        port: 3000
    },
    plugins: [
        new htmlWebpackPlugin({
            // 指定 html 模板位置
            template: "./public/index.html"
        }),
        new CleanWebpackPlugin(), // 打包清空 dist
    ],
    module: {
        rules: [
            {
                test: /\.ts$/, // 解析 ts
                loader: "ts-loader",
                exclude: /node_modules/
            }
        ]
    }
}
module.exports = config

配置别名 @,替换 src

在 resolve 中,进行配置

js 复制代码
// 增加代码智能提示
const { Configuration } = require('webpack')
const path = require('path')
const htmlWebpackPlugin = require('html-webpack-plugin')
const { CleanWebpackPlugin } = require('clean-webpack-plugin')
/**
 * @type { Configuration } // 使用注解的方式,增加代码智能提示
 */

const config = {
    mode: "development",
    // 入口文件
    entry: './src/main.ts',
    // 出口文件
    output: {
        filename: "[hash].js",
        path: path.resolve(__dirname, 'dist')
    },
    devServer: {
        open: true,
        host: "localhost",
        port: 3000
    },
    plugins: [
        new htmlWebpackPlugin({
            // 指定 html 模板位置
            template: "./public/index.html"
        }),
        new CleanWebpackPlugin(), // 打包清空 dist
    ],
    module: {
        rules: [
            {
                test: /\.ts$/, // 解析 ts
                loader: "ts-loader",
                exclude: /node_modules/
            }
        ]
    },
    resolve: {
        alias: {
            "@": path.resolve(__dirname, './src') // 别名
        },
        extensions: ['.js', '.json', '.vue', '.ts', '.tsx'] // 识别后缀
    }
}
module.exports = config

安装样式相关 loader

安装样式相关 loader,协助 webpack 解析样式

新建 index.css,随便写点样式

利用设置好的别名 @,在 main.ts 中进行引入,发现报错了

可以看出 webpack 不会处理 css 的,需要安装一些 loader 协助 webpack 处理样式。 即style-loadercss-loader

(1)安装

  • 处理 css 语法yarn add -D style-loader css-loader
  • 处理 less 语法 yarn add lessyarn add less-loader

(2)在webpack.config.js 中,补充配置

js 复制代码
// 增加代码智能提示
const { Configuration } = require('webpack')
const path = require('path')
const htmlWebpackPlugin = require('html-webpack-plugin')
const { CleanWebpackPlugin } = require('clean-webpack-plugin')
/**
 * @type { Configuration } // 使用注解的方式,增加代码智能提示
 */

const config = {
    mode: "development",
    // 入口文件
    entry: './src/main.ts',
    // 出口文件
    output: {
        filename: "[hash].js",
        path: path.resolve(__dirname, 'dist')
    },
    devServer: {
        open: true,
        host: "localhost",
        port: 3000
    },
    plugins: [
        new htmlWebpackPlugin({
            // 指定 html 模板位置
            template: "./public/index.html"
        }),
        new CleanWebpackPlugin(), // 打包清空 dist
    ],
    module: {
        rules: [
            {
                test: /\.ts$/, // 解析 ts
                loader: "ts-loader",
                exclude: /node_modules/
            },
            {
                test: /\.css$/, // 解析 css
                use: ["style-loader", "css-loader"],
            },
            {
                test: /\.less$/, // 解析 less
                use: ["style-loader", "css-loader", "less-loader"],
            },
        ]
    },
    resolve: {
        alias: {
            "@": path.resolve(__dirname, './src') // 别名
        },
        extensions: ['.js', '.json', '.vue', '.ts', '.tsx'] // 识别后缀
    }
}
module.exports = config

添加Vue及其相关配置

(1)安装并引入vue

安装 vue

js 复制代码
yarn add vue

在 main.ts 中,引入 vue

js 复制代码
import { createApp } from 'vue'
import App from './App.vue'
// 注意:这里的 #app,需要在 public/index.html 中,写一个 id 为 app 的 div
createApp(App).mount('#app')

会发现各种爆红,因为 ts 此时还不认识 vue 呢,所以需要增加 vue 声明文件

(2)补充vue声明文件

项目根目录下,新建 env.d.ts

ts 复制代码
declare module "*.vue" {
   import { DefineComponent } from "vue"
   const component: DefineComponent<{}, {}, any>
   export default component
}

这样,main.ts 里就不会爆红了,因为 ts 现在认识 vue

(3)增加 vue 相关 webpack 配置,打包 vue 文件

直接打包会报错,此时webpack不认识 template 之类的标签

需要安装 loader,协助 webpack 解析 vue 相关标签、文件

V3

js 复制代码
yarn add vue-loader@next
yarn add @vue/compiler-sfc

V2

js 复制代码
// 先执行下面2行命令,安装具体的 2.x 版本
yarn add vue-loader
yarn add vue@2.6.14
yarn add vue-template-compiler@2.6.14

vue-template-compiler说明:

vue-template-compiler 用于将 Vue 模板和单文件组件 编译成 JavaScript。 大多数开发人员不直接使用 vue-template-compiler。 但是像用于 Webpack 的 vue-loader 之 使用 vue-template-compiler 来完成实际编译的繁重工作.vue文件。

vue-template-compiler 有两个主要功能:将模板转换为render() 函数 和解析单个文件组件 。

这个包可用于将Vue 2.0模板预编译为呈现函数,以避免运行时编译开销和CSP限制。在大多数情况下,应该将它与vue-loader一起使用,只有在编写具有非常特定需求的构建工具时才会单独使用它。

在 vue 工程中,安装依赖时,需要 vue 和 vue-template-compiler 版本必须保持一致

vue-template-compiler在 v3 中被@vue/compiler-sfc取代

(4)在 webpack.config.js 中,补充配置

js 复制代码
// 增加代码智能提示
const { Configuration } = require('webpack')
const path = require('path')
const htmlWebpackPlugin = require('html-webpack-plugin')
const { CleanWebpackPlugin } = require('clean-webpack-plugin')
const { VueLoaderPlugin } = require('vue-loader/dist/index')
/**
 * @type { Configuration } // 使用注解的方式,增加代码智能提示
 */

// console.log('process.env.NODE_ENV', process.env.NODE_ENV)
const config = {
    mode: "development",
    // 入口文件
    entry: './src/main.ts',
    // 出口文件
    output: {
        filename: "[hash].js",
        path: path.resolve(__dirname, 'dist')
    },
    devServer: {
        open: true,
        host: "localhost",
        port: 3000
    },
    plugins: [
        new htmlWebpackPlugin({
            // 指定 html 模板位置
            template: "./public/index.html"
        }),
        new CleanWebpackPlugin(), // 打包清空 dist
        new VueLoaderPlugin(), // 解析 vue 模板
    ],
    module: {
        rules: [
            {
                test: /\.ts$/, // 解析 ts
                loader: "ts-loader",
                exclude: /node_modules/
                // options: {
                //     configFile: path.resolve(process.cwd(), 'tsconfig.json'),
                //     appendTsSuffixTo: [/\.vue$/]
                // },
            },
            {
                test: /\.css$/, // 解析 css
                use: ["style-loader", "css-loader"],
            },
            {
                test: /\.vue$/, // 解析 .vue 结尾的文件
                use: "vue-loader"
            },
        ]
    },
    resolve: {
        alias: {
            "@": path.resolve(__dirname, './src') // 别名
        },
        extensions: ['.js', '.json', '.vue', '.ts', '.tsx'] // 识别后缀
    }
}
module.exports = config

最终

项目结构

package.json

js 复制代码
{
  "name": "helloInit3",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1",
    "dev": "webpack-dev-server",
    "build": "webpack"
  },
  "keywords": [],
  "author": "",
  "license": "ISC",
  "dependencies": {
    "@vue/compiler-sfc": "^3.4.5",
    "less": "^4.2.0",
    "less-loader": "^11.1.4",
    "vue": "^3.4.5",
    "vue-loader": "^17.4.2",
    "webpack": "^5.89.0",
    "webpack-cli": "^5.1.4",
    "webpack-dev-server": "^4.15.1"
  },
  "devDependencies": {
    "clean-webpack-plugin": "^4.0.0",
    "css-loader": "^6.8.1",
    "html-webpack-plugin": "^5.6.0",
    "style-loader": "^3.3.3",
    "ts-loader": "^9.5.1",
    "typescript": "^5.3.3"
  }
}

发布包到npm

如果需要发布到NPM上需要,指定npm 包上传内容

修改package.json 修改mainfiles ,新增 types字段。

具体配置举例如下:

js 复制代码
{
  "name": "webpack5-ts-lib-boilerplate",
  "version": "1.0.0",
  "description": "My webpack project",
  "author": "ZY",
  "license": "MIT",
  "main": "./dist/main.js",
  "types": "./dist/types/index.d.ts",
  "files": [
    "dist"
  ],
  "devDependencies": {
    "@webpack-cli/generators": "^2.4.1",
    "autoprefixer": "^10.4.2",
    "css-loader": "^6.5.1",
    "html-webpack-plugin": "^5.5.0",
    "less": "^4.1.2",
    "less-loader": "^10.2.0",
    "postcss": "^8.4.5",
    "postcss-loader": "^6.2.1",
    "prettier": "^2.5.1",
    "style-loader": "^3.3.1",
    "ts-loader": "^9.2.6",
    "typescript": "^4.5.4",
    "webpack": "^5.66.0",
    "webpack-cli": "^4.9.1",
    "webpack-dev-server": "^4.7.3"
  },
  "scripts": {
    "build": "webpack --mode=production --node-env=production",
    "build:dev": "webpack --mode=development",
    "build:prod": "webpack --mode=production --node-env=production",
    "watch": "webpack --watch",
    "serve": "webpack serve"
  }
}

补充:

js 复制代码
base.devServer = {
  // contentBase: path.join(__dirname, "dist"),
  compress: true,
  port: 12345,
  hot: true,
  disableHostCheck: true,
  progress: false,
  clientLogLevel: 'none',
  overlay: true,
  quiet: true,
  host: '0.0.0.0',
  proxy: {
    '/api': {
      target: `http://${ip}:${webport}`,
      pathRewrite: {
        '^/api': '/api'
      }
    },

  }
}
相关推荐
九月十九19 分钟前
AviatorScript用法
java·服务器·前端
_.Switch1 小时前
Python Web开发:使用FastAPI构建视频流媒体平台
开发语言·前端·python·微服务·架构·fastapi·媒体
菜鸟阿康学习编程2 小时前
JavaWeb 学习笔记 XML 和 Json 篇 | 020
xml·java·前端
索然无味io2 小时前
XML外部实体注入--漏洞利用
xml·前端·笔记·学习·web安全·网络安全·php
ThomasChan1233 小时前
Typescript 多个泛型参数详细解读
前端·javascript·vue.js·typescript·vue·reactjs·js
爱学习的狮王3 小时前
ubuntu18.04安装nvm管理本机node和npm
前端·npm·node.js·nvm
东锋1.33 小时前
使用 F12 查看 Network 及数据格式
前端
zhanggongzichu3 小时前
npm常用命令
前端·npm·node.js
anyup_前端梦工厂3 小时前
从浏览器层面看前端性能:了解 Chrome 组件、多进程与多线程
前端·chrome
chengpei1473 小时前
chrome游览器JSON Formatter插件无效问题排查,FastJsonHttpMessageConverter导致Content-Type返回不正确
java·前端·chrome·spring boot·json