为什么要手写webpack 不用cli (无的放矢)并不是 其实是为了加深我们对webpack 的了解方便以后灵活运用webpack 的技术
- 初始化项目结构(跟cli 结构保持一致)
- 新建 public src 等文件夹
- npm init -y 创建package.json文件
- tsc --init 创建 tsconfig.json 文件
注:如果没有tsc的话 终端执行 npm install typescript -g 命令然后再执行 tsc --init 命令
- 然后在 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>
- 在根目录下创建 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}
*/
- 修改 main.ts文件
import { createApp } from 'vue'
import App from './App.vue'
createApp(App).mount('#app')
- 在src 文件夹下新建 env.d.ts 文件
配置vue生命文件不然ts 识别不了vue后缀
declare module "*.vue" {
import { DefineComponent } from "vue"
const component: DefineComponent<{}, {}, any>
export default component
}
- 安装 loader 解析sfc
pnpm add vue-loader@next //解析vue
pnpm add @vue/compiler-sfc //解析vue文件
- 配置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;
-
打包的时候清空dist 就不用做手动删除了
pnpm add clean-webpack-plugin -
配置别名 @ 代表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;
- 安装插件解析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;
- 识别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;
- 美化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;
- 配置 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;
- 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"
}