webpack从零到1 构建 vue3

发布于:2024-05-09 ⋅ 阅读:(34) ⋅ 点赞:(0)

为什么要手写webpack 不用cli (无的放矢)并不是 其实是为了加深我们对webpack 的了解方便以后灵活运用webpack 的技术

  1. 初始化项目结构(跟cli 结构保持一致)
    • 新建 public src 等文件夹
    • npm init -y 创建package.json文件
    • tsc --init 创建 tsconfig.json 文件
      注:如果没有tsc的话 终端执行 npm install typescript -g 命令然后再执行 tsc --init 命令
  2. 然后在 src文件夹下 创建以下文件
    在这里插入图片描述

3.在public 文件夹下创建 index.html

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>webpack demo</title>
</head>

<body>
    <div id="app"></div>
</body>

</html>
  1. 在根目录下创建 webpack.config.js 文件 然后在终端执行以下命令
pnpm add webpack
pnpm add webpack-cli // 如果webpack 是3以上的版本 需要再配套安装
// 启动 dev 的环境
pnpm add webpack-dev-server
// html 模板
pnpm add html-webpack-plugin 
// 安装vue
pnpm add vue

5.webpack.config.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({
			template: "./public/index.html",
		}),
	],
};
module.exports = config;

注:想在webpack.config.js 文件中获得智能提示 需要 以下代码

const { Configuration } = require("webpack"); // 智能提示
/**
  @type {Configuration}
 */
  1. 修改 main.ts文件
import { createApp } from 'vue'
import App from './App.vue'
createApp(App).mount('#app')
  1. 在src 文件夹下新建 env.d.ts 文件
    配置vue生命文件不然ts 识别不了vue后缀
 
declare module "*.vue" {
    import { DefineComponent } from "vue"
    const component: DefineComponent<{}, {}, any>
    export default component
  }
  1. 安装 loader 解析sfc
pnpm add vue-loader@next //解析vue
pnpm add @vue/compiler-sfc //解析vue文件
  1. 配置webpack.config.js 文件
    const { VueLoaderPlugin } = require(‘vue-loader/dist/index’);
    然后再plugins里注册下
    new VueLoaderPlugin(), //解析vue
const { Configuration } = require("webpack"); // 智能提示
const path = require("path");
const htmlWebpackPlugin = require("html-webpack-plugin");
const { VueLoaderPlugin } = require("vue-loader/dist/index");
/**
 * @type {Configuration}
 */
const config = {
	mode: "development",
	entry: "./src/main.ts", // 入口文件
	module: {
		rules: [
			{
				test: /\.vue$/, //解析vue 模板
				use: "vue-loader",
			},
		],
	},
	output: {
		// 出口文件 打完包出口在哪
		filename: "[hash].js",
		path: path.resolve(__dirname, "dist"),
	},
	plugins: [
		new htmlWebpackPlugin({
			template: "./public/index.html",
		}),
		new VueLoaderPlugin(), //解析vue
	],
};
module.exports = config;

  1. 打包的时候清空dist 就不用做手动删除了
    pnpm add clean-webpack-plugin

  2. 配置别名 @ 代表src
    修改 webpack.config.js 文件 进行别名 添加 resolve 属性

const { Configuration } = require("webpack"); // 智能提示
const path = require("path");
const htmlWebpackPlugin = require("html-webpack-plugin");
const { VueLoaderPlugin } = require("vue-loader/dist/index");
/**
 * @type {Configuration}
 */
const config = {
	mode: "development",
	entry: "./src/main.ts", // 入口文件
	module: {
		rules: [
			{
				test: /\.vue$/, //解析vue 模板
				use: "vue-loader",
			},
		],
	},
	output: {
		// 出口文件 打完包出口在哪
		filename: "[hash].js",
		path: path.resolve(__dirname, "dist"),
	},
	resolve: {
		alias: {
			"@": path.resolve(__dirname, "src"),
		},
		extensions: [".vue", ".ts", ".js"], // 自动补全后缀
	},
	plugins: [
		new htmlWebpackPlugin({
			template: "./public/index.html",
		}),
		new VueLoaderPlugin(), //解析vue
	],
};
module.exports = config;
  1. 安装插件解析css 并配置webpack.config.json
    pnpm add css-loader 解析css 文件
    pnpm add style-loader 解析 css 样式
    也可以安装 less、scss
    pnpm add less
    pnpm add less-loader
    配置 webpack.config.json 文件
const { Configuration } = require("webpack"); // 智能提示
const path = require("path");
const htmlWebpackPlugin = require("html-webpack-plugin");
const { VueLoaderPlugin } = require("vue-loader/dist/index");
/**
 * @type {Configuration}
 */
const config = {
	mode: "development",
	entry: "./src/main.ts", // 入口文件
	module: {
		rules: [
			{
				test: /\.vue$/, //解析vue 模板
				use: "vue-loader",
			},
			{
				test: /\.css$/, //解析css
				use: ["style-loader", "css-loader"],
			},
			{
				test: /\.less$/, //解析 less
				use: ["style-loader", "css-loader", "less-loader"],
			},
		],
	},
	output: {
		// 出口文件 打完包出口在哪
		filename: "[hash].js",
		path: path.resolve(__dirname, "dist"),
	},
	resolve: {
		alias: {
			"@": path.resolve(__dirname, "src"),
		},
		extensions: [".vue", ".ts", ".js"], // 自动补全后缀
	},
	plugins: [
		new htmlWebpackPlugin({
			template: "./public/index.html",
		}),
		new VueLoaderPlugin(), //解析vue
	],
};
module.exports = config;
  1. 识别ts
pnpm add typescript
pnpm add ts-loader

修改webpack.config.js

const { Configuration } = require("webpack"); // 智能提示
const path = require("path");
const htmlWebpackPlugin = require("html-webpack-plugin");
const { VueLoaderPlugin } = require("vue-loader/dist/index");
/**
 * @type {Configuration}
 */
const config = {
	mode: "development",
	entry: "./src/main.ts", // 入口文件
	module: {
		rules: [
			{
				test: /\.vue$/, //解析vue 模板
				use: "vue-loader",
			},
			{
				test: /\.css$/, //解析css
				use: ["style-loader", "css-loader"],
			},
			{
				test: /\.less$/, //解析 less
				use: ["style-loader", "css-loader", "less-loader"],
			},
			{
				test: /\.ts$/, //解析ts
				loader: "ts-loader",
				options: {// 需要对单文件做特殊处理
					configFile: path.resolve(process.cwd(), "tsconfig.json"),
					appendTsSuffixTo: [/\.vue$/],
				},
			},
		],
	},
	output: {
		// 出口文件 打完包出口在哪
		filename: "[hash].js",
		path: path.resolve(__dirname, "dist"),
	},
	resolve: {
		alias: {
			"@": path.resolve(__dirname, "src"),
		},
		extensions: [".vue", ".ts", ".js"], // 自动补全后缀
	},
	plugins: [
		new htmlWebpackPlugin({
			template: "./public/index.html",
		}),
		new VueLoaderPlugin(), //解析vue
	],
};
module.exports = config;

  1. 美化webpack 控制台日志的
    pnpm add friendly-errors-webpack-plugin
const { Configuration } = require("webpack"); // 智能提示
const path = require("path");
const htmlWebpackPlugin = require("html-webpack-plugin");
const { VueLoaderPlugin } = require("vue-loader/dist/index");
const FriendlyErrorsWebpackPlugin = require("friendly-errors-webpack-plugin");
/**
 * @type {Configuration}
 */
const config = {
	mode: "development",
	entry: "./src/main.ts", // 入口文件
	module: {
		rules: [
			// 处理文件
			{
				test: /\.vue$/, //解析vue 模板
				use: "vue-loader",
			},
			{
				test: /\.css$/, //解析css
				use: ["style-loader", "css-loader"],
			},
			{
				test: /\.less$/, //解析 less
				use: ["style-loader", "css-loader", "less-loader"],
			},
			{
				test: /\.ts$/, //解析ts
				loader: "ts-loader",
				options: {
					// 需要对单文件做特殊处理
					configFile: path.resolve(process.cwd(), "tsconfig.json"),
					appendTsSuffixTo: [/\.vue$/],
				},
			},
		],
	},
	output: {
		// 出口文件 打完包出口在哪
		filename: "[hash].js",
		path: path.resolve(__dirname, "dist"),
	},
	resolve: {
		alias: {
			"@": path.resolve(__dirname, "src"),
		},
		extensions: [".vue", ".ts", ".js"], // 自动补全后缀
	},
	stats: "errors-only", // 去掉一些没有用的提示
	plugins: [
		// 只要放在plugins里面都是插件
		new htmlWebpackPlugin({
			template: "./public/index.html",
		}),
		new VueLoaderPlugin(), //解析vue
		new FriendlyErrorsWebpackPlugin({
			compilationSuccessInfo: {
				messages: ["you this hear:http://localhost:8080"],
			},
		}),
	],
};
module.exports = config;
  1. 配置 devServer 可修改端口 指定地址等
const { Configuration } = require("webpack"); // 智能提示
const path = require("path");
const htmlWebpackPlugin = require("html-webpack-plugin");
const { VueLoaderPlugin } = require("vue-loader/dist/index");
const FriendlyErrorsWebpackPlugin = require("friendly-errors-webpack-plugin");
/**
 * @type {Configuration}
 */
const config = {
	mode: "development",
	entry: "./src/main.ts", // 入口文件
	module: {
		rules: [
			// 处理文件
			{
				test: /\.vue$/, //解析vue 模板
				use: "vue-loader",
			},
			{
				test: /\.css$/, //解析css
				use: ["style-loader", "css-loader"],
			},
			{
				test: /\.less$/, //解析 less
				use: ["style-loader", "css-loader", "less-loader"],
			},
			{
				test: /\.ts$/, //解析ts
				loader: "ts-loader",
				options: {
					// 需要对单文件做特殊处理
					configFile: path.resolve(process.cwd(), "tsconfig.json"),
					appendTsSuffixTo: [/\.vue$/],
				},
			},
		],
	},
	output: {
		// 出口文件 打完包出口在哪
		filename: "[hash].js",
		path: path.resolve(__dirname, "dist"),
	},
	resolve: {
		alias: {
			"@": path.resolve(__dirname, "src"),
		},
		extensions: [".vue", ".ts", ".js"], // 自动补全后缀
	},
	devServer: {
		port: 9001,
	},
	stats: "errors-only", // 去掉一些没有用的提示
	plugins: [
		// 只要放在plugins里面都是插件
		new htmlWebpackPlugin({
			template: "./public/index.html",
		}),
		new VueLoaderPlugin(), //解析vue
		new FriendlyErrorsWebpackPlugin({
			compilationSuccessInfo: {
				messages: ["you this hear:http://localhost:8080"],
			},
		}),
	],
};
module.exports = config;
  1. externals 性能优化
const { Configuration } = require("webpack"); // 智能提示
const path = require("path");
const htmlWebpackPlugin = require("html-webpack-plugin");
const { VueLoaderPlugin } = require("vue-loader/dist/index");
const FriendlyErrorsWebpackPlugin = require("friendly-errors-webpack-plugin");
/**
 * @type {Configuration}
 */
const config = {
	mode: "development",
	entry: "./src/main.ts", // 入口文件
	module: {
		rules: [
			// 处理文件
			{
				test: /\.vue$/, //解析vue 模板
				use: "vue-loader",
			},
			{
				test: /\.css$/, //解析css
				use: ["style-loader", "css-loader"],
			},
			{
				test: /\.less$/, //解析 less
				use: ["style-loader", "css-loader", "less-loader"],
			},
			{
				test: /\.ts$/, //解析ts
				loader: "ts-loader",
				options: {
					// 需要对单文件做特殊处理
					configFile: path.resolve(process.cwd(), "tsconfig.json"),
					appendTsSuffixTo: [/\.vue$/],
				},
			},
		],
	},
	output: {
		// 出口文件 打完包出口在哪
		filename: "[hash].js",
		path: path.resolve(__dirname, "dist"),
	},
	resolve: {
		alias: {
			"@": path.resolve(__dirname, "src"),
		},
		extensions: [".vue", ".ts", ".js"], // 自动补全后缀
	},
	devServer: {
		port: 9001,
	},
	stats: "errors-only", // 去掉一些没有用的提示
	plugins: [
		// 只要放在plugins里面都是插件
		new htmlWebpackPlugin({
			template: "./public/index.html",
		}),
		new VueLoaderPlugin(), //解析vue
		new FriendlyErrorsWebpackPlugin({
			compilationSuccessInfo: {
				messages: ["you this hear:http://localhost:8080"],
			},
		}),
	],
	externals: {
		vue:'Vue'
	}
};
module.exports = config;

最终的 package.json 包详解

{
    "name": "webpack-vue",
    "version": "1.0.0",
    "description": "",
    "main": "webpack.config.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.2.38", //解析vue文件
        "clean-webpack-plugin": "^4.0.0", //打包 的时候清空dist
        "css-loader": "^6.7.1", //处理css文件
        "friendly-errors-webpack-plugin": "^1.7.0", //美化dev
        "html-webpack-plugin": "^5.5.0", //html 模板
        "less": "^4.1.3",  //处理less
        "less-loader": "^11.0.0", //处理less文件
        "style-loader": "^3.3.1", //处理style样式
        "ts-loader": "^9.3.1", //处理ts
        "typescript": "^4.8.2", //ts
        "vue": "^3.2.38", //vue
        "vue-loader": "^17.0.0", //解析vue
        "webpack": "^5.74.0",
        "webpack-cli": "^4.10.0",
        "webpack-dev-server": "^4.10.0"
    }