webpack使用详细步骤

项目描述

本项目 webpack 的基本使用。

webpack 官方:https://webpack.docschina.org/concepts/

Element-plus 官方:https://element-plus.sxtxhy.com/zh-CN/

Vue3 官方:https://cn.vuejs.org/

项目组成明细

每个步骤完成后重新执行 npm run dev 即可看到效果

1、webpack

打包工具

安装

bash 复制代码
npm install webpack --save-dev

package.json

配置 dev 命令

json 复制代码
{
  "name": "test",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "dev": "npx webpack --config webpack.dev.js"
  },
  "keywords": [],
  "author": "",
  "license": "ISC",
  "devDependencies": {
    "webpack": "^5.98.0"
  }
}

入口文件 main.js

创建 src 文件夹,创建文件 main.js

js 复制代码
const h1 = document.createElement('h1')
h1.innerHTML = '666'
document.body.appendChild(h1)

console.log(h1)
console.log(process.env.NODE_ENV === 'development')

配置文件 webpack.dev.js

js 复制代码
const path = require('path')

module.exports = {
  mode: 'development', // 开发模式

  // 入口文件
  entry: {
    dev_index: './src/main.js' // 这个对象的键名会传递到下面的'[name].bundle.js'中的 name
  },

  // 输出文件
  output: {
    filename: '[name].bundle.js', // 输出文件名
    path: path.resolve(__dirname, 'dist') // 输出文件目录
  },
  devtool: 'inline-source-map' // 开启source-map
}

2、html-webpack-plugin

生成 html 文件

安装

bash 复制代码
npm install html-webpack-plugin --save-dev

package.json

json 复制代码
{
  // ...
  "devDependencies": {
    "webpack": "^5.98.0",
    "html-webpack-plugin": "^5.6.3"
  }
}

创建文件 index.html

src 下面创建文件 index.html

html 复制代码
<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8" />
    <title><%= htmlWebpackPlugin.options.title %></title>
  </head>
  <body>
    <div id="app"></div>
  </body>
</html>

webpack.dev.js

js 复制代码
const path = require('path')
const HtmlWebpackPlugin = require('html-webpack-plugin')

module.exports = {
  // ...

  plugins: [
    new HtmlWebpackPlugin({
      title: 'template5-dev', // 生成的HTML文件标题
      filename: 'index.html' // 生成的HTML文件名
      template: './src/index.html', // 不配置此项,默认生成index.html;配置此项传递自定义HTML文件
      // favicon: path.join(__dirname, './src/img/favicon.ico')
    })
  ]
}

3、webpack-dev-server

启动一个本地服务器,并实时更新页面

安装

bash 复制代码
npm install webpack-dev-server --save-dev

package.json

dev 命令增加 serve

json 复制代码
{
  // ...
  "scripts": {
    "dev": "npx webpack serve --config webpack.dev.js"
  },
  // ...
  "devDependencies": {
    "webpack": "^5.98.0",
    "html-webpack-plugin": "^5.6.3",
    "webpack-dev-server": "^5.2.0"
  }
}

webpack.dev.js

js 复制代码
const path = require('path')
const HtmlWebpackPlugin = require('html-webpack-plugin')

module.exports = {
  // ...

  devServer: {
    static: './dist', // 静态资源目录
    hot: true, // 开启模块热更新
    port: 8080, // 端口号
    open: true, // 自动打开浏览器
    watchFiles: ['./src/index.html'], // 监听文件变化(自动刷新页面)
    client: {
      logging: 'none' // 关闭客户端日志
      // logging: 'error', // 仅显示错误
    }
  }
}

4、style-loader、css-loader

处理 css 文件

安装

bash 复制代码
npm install style-loader css-loader --save-dev

package.json

json 复制代码
{
  // ...
  "devDependencies": {
    "webpack": "^5.98.0",
    "html-webpack-plugin": "^5.6.3",
    "webpack-dev-server": "^5.2.0",
    "style-loader": "^4.0.0",
    "css-loader": "^7.1.2"
  }
}

main.js

src 下面创建 css 文件夹,里面创建 index.css

js 复制代码
// ...
import './css/index.css'

webpack.dev.js

js 复制代码
const path = require('path')
const HtmlWebpackPlugin = require('html-webpack-plugin')

module.exports = {
  // ...

  module: {
    rules: [
      {
        test: /\.css$/i, // 匹配css文件
        use: ['style-loader', 'css-loader'] // 使用loader
      }
    ]
  }
}

5、url-loader

处理图片、字体等静态资源

安装

bash 复制代码
npm install url-loader --save-dev

package.json

json 复制代码
{
  // ...
  "devDependencies": {
    "webpack": "^5.98.0",
    "html-webpack-plugin": "^5.6.3",
    "webpack-dev-server": "^5.2.0",
    "style-loader": "^4.0.0",
    "css-loader": "^7.1.2",
    "url-loader": "^4.1.1"
  }
}

main.js

src 下面创建 img 文件夹, 添加 favicon.ico 文件

js 复制代码
// ...
import img from './img/favicon.ico'

console.log(img)
document.body.appendChild(img)

webpack.dev.js

js 复制代码
const path = require('path')
const HtmlWebpackPlugin = require('html-webpack-plugin')

module.exports = {
  // ...

  module: {
    rules: [
      // ...
      {
        test: /\.(png|svg|jpg|jpeg|gif)$/i, // 匹配图片文件
        use: [{ loader: 'url-loader', options: { limit: 6000, esModule: false, name: '[name].[ext]', outputPath: 'images' } }], // 使用loader
        type: 'javascript/auto' // 解决图片打包后路径问题
      }
    ]
  }
}

6、terser-webpack-plugin

压缩代码,去掉注释与 console.log 等 [生产环境时配置]

安装

bash 复制代码
npm install terser-webpack-plugin --save-dev

package.json

增加 build 命令

json 复制代码
{
  // ...
  "scripts": {
    "dev": "npx webpack serve --config webpack.dev.js",
    "build": "npx webpack --config webpack.prod.js"
  },
  // ...
  "devDependencies": {
    "webpack": "^5.98.0",
    "html-webpack-plugin": "^5.6.3",
    "webpack-dev-server": "^5.2.0",
    "style-loader": "^4.0.0",
    "css-loader": "^7.1.2",
    "url-loader": "^4.1.1",
    "terser-webpack-plugin": "^5.3.14"
  }
}

创建文件 webpack.prod.js

生产环境配置文件

js 复制代码
const path = require('path')
const HtmlWebpackPlugin = require('html-webpack-plugin')
const TerserPlugin = require('terser-webpack-plugin')

module.exports = {
  mode: 'production',
  entry: {
    index: './src/main.js'
  },
  output: {
    publicPath: './',
    filename: '[name].js',
    path: path.resolve(__dirname, 'dist'),
    clean: true
  },
  plugins: [
    new HtmlWebpackPlugin({
      title: 'template5',
      filename: 'index.html',
      template: './src/index.html',
      favicon: path.join(__dirname, './src/img/favicon.ico')
    })
  ],
  module: {
    rules: [
      {
        test: /\.css$/i,
        use: ['style-loader', 'css-loader']
      },
      {
        test: /\.(png|svg|jpg|jpeg|gif)$/i,
        use: [{ loader: 'url-loader', options: { limit: 6000, esModule: false, name: '[name].[ext]', outputPath: 'images' } }],
        type: 'javascript/auto'
      }
    ]
  },

  optimization: {
    minimizer: [
      new TerserPlugin({
        terserOptions: {
          compress: {
            drop_console: true // 移除所有 console.*
          },
          format: {
            comments: false // 移除所有注释
          }
        },
        extractComments: false // 禁止生成独立的注释文件
      })
    ]
  }
}

7、vue-loader

处理 vue 文件

安装

bash 复制代码
npm install vue-loader --save-dev

安装 vue3

bash 复制代码
npm install vue

package.json

json 复制代码
{
  // ...
  "dependencies": {
    "vue": "^3.5.13"
  },
  "devDependencies": {
    "webpack": "^5.98.0",
    "html-webpack-plugin": "^5.6.3",
    "webpack-dev-server": "^5.2.0",
    "style-loader": "^4.0.0",
    "css-loader": "^7.1.2",
    "url-loader": "^4.1.1",
    "terser-webpack-plugin": "^5.3.14",
    "vue-loader": "^17.4.2"
  }
}

创建文件 App.vue

src 下面创建 App.vue

vue 复制代码
<template>
  <header>
    <h1>{{ test_name }}</h1>
  </header>
  <main></main>
  <footer></footer>
</template>

<script setup>
import { ref } from 'vue'

const test_name = ref('app.vue')
</script>

main.js

js 复制代码
// ...
import { createApp } from 'vue'
import App from './App.vue'

const app = createApp(App)
app.mount('#app')

webpack.dev.js

js 复制代码
const path = require('path')
const HtmlWebpackPlugin = require('html-webpack-plugin')
const { VueLoaderPlugin } = require('vue-loader')

module.exports = {
  // ...

  plugins: [
    // ...
    new VueLoaderPlugin() // 添加VueLoaderPlugin
  ],

  // ...

  module: {
    rules: [
      // ...
      {
        test: /\.vue$/,
        loader: 'vue-loader'
      }
    ]
  }
}

7.1 不使用 vue-loader 加载 vue

不使用 vue-loader 插件,也可以使用 vue 的方法

此法打包后项目大些,编译速度慢些,正常不推荐

main.js

js 复制代码
// ...
import { createApp } from 'vue'

createApp({
  data() {
    return {
      msg: 'Hello Vue!'
    }
  }
}).mount('#app')

index.html

html 复制代码
<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8" />
    <title><%= htmlWebpackPlugin.options.title %></title>
  </head>
  <body>
    <div id="app">{{ msg }}</div>
  </body>
</html>

webpack.dev.js

打包生产时也要加上此配置

js 复制代码
const path = require('path')
const HtmlWebpackPlugin = require('html-webpack-plugin')

module.exports = {
  // ...

  resolve: {
    alias: {
      vue$: 'vue/dist/vue.esm-bundler.js' // 包含编译器的构建版本
    }
  }
}

8、全局加载 Element plus

全局加载打包后项目偏大,但配置简单

安装

bash 复制代码
npm install element-plus

package.json

json 复制代码
{
  // ...
  "dependencies": {
    "vue": "^3.5.13",
    "element-plus": "^2.9.6"
  }
  // ...
}

main.js

js 复制代码
// ...
import { createApp } from 'vue'
import App from './App.vue'
import ElementPlus from 'element-plus'
import 'element-plus/dist/index.css'
import zhCn from 'element-plus/dist/locale/zh-cn.mjs'

const app = createApp(App)

app.use(ElementPlus, {
  locale: zhCn
})

app.mount('#app')

8.1、按需加载 Element plus

按需加载打包后项目偏小,但配置复杂,并且需要安装插件

安装插件

安装旧版,因最新版默认导出 ESM 格式,不支持 CommonJS 格式

bash 复制代码
npm install unplugin-auto-import@0.16.1 unplugin-vue-components@0.25.1 --save-dev

main.js

无需配置,如之前已配置全局 Element plus,需去掉

js 复制代码
// ...
import { createApp } from 'vue'
import App from './App.vue'

const app = createApp(App)
app.mount('#app')

App.vue

使用方法,并配置国际化

vue 复制代码
<template>
  <el-config-provider :locale="zhCn">
    <el-button type="primary" @click="testOpen('test')">test</el-button>
  </el-config-provider>
</template>

<script setup>
import { ref } from 'vue'
import { ElConfigProvider } from 'element-plus'
import zhCn from 'element-plus/dist/locale/zh-cn.mjs'

const testOpen = (name) => {
  ElMessage('this is a message.')
}
</script>

webpack.dev.js

js 复制代码
const path = require('path')
const HtmlWebpackPlugin = require('html-webpack-plugin')
const { VueLoaderPlugin } = require('vue-loader')
const AutoImport = require('unplugin-auto-import/webpack')
const Components = require('unplugin-vue-components/webpack')
const { ElementPlusResolver } = require('unplugin-vue-components/resolvers')

module.exports = {
  // ...

  plugins: [
    // ...
    AutoImport({
      resolvers: [ElementPlusResolver()]
    }),
    Components({
      resolvers: [ElementPlusResolver()]
    })
  ]

  // ...
}

9、axios

请求 axios

安装

bash 复制代码
npm install axios

package.json

json 复制代码
{
  // ...
  "dependencies": {
    "vue": "^3.5.13",
    "element-plus": "^2.9.6",
    "axios": "^1.8.4"
  }
  // ...
}

创建 api.js

在 src 目录下创建 api.js

js 复制代码
import axios from 'axios'

const api = axios.create({
  baseURL: 'http://localhost:9000',
  timeout: 60000,
  headers: { ['Content-Type']: 'application/x-www-form-urlencoded' }
  // withCredentials: true // 跨域请求时是否需要使用凭证(携带cookie)
})

// 请求拦截器
api.interceptors.request.use(
  (req) => {
    return req
  },
  (err) => {
    return Promise.reject(err)
  }
)

// 响应拦截器
api.interceptors.response.use(
  (res) => {
    return res.data
  },
  (err) => {
    return Promise.reject(err)
  }
)

const { get, post, put, delete: del } = api

export const testGet = (params) => {
  return get('/tianqiApi', { params })
}

App.vue

vue 复制代码
<template>
  <!-- // ... -->
</template>

<script setup>
// ...

import { testGet } from './api'

const testApi = async () => {
  try {
    const res = await testGet()
    console.log(res)
  } catch (error) {
    console.log(error)
  }
}

testApi()
</script>

完整配置 webpack.dev.js

开发配置

js 复制代码
const path = require('path')
const HtmlWebpackPlugin = require('html-webpack-plugin')
const { VueLoaderPlugin } = require('vue-loader')
const AutoImport = require('unplugin-auto-import/webpack')
const Components = require('unplugin-vue-components/webpack')
const { ElementPlusResolver } = require('unplugin-vue-components/resolvers')

module.exports = {
  mode: 'development', // 开发模式

  // 入口文件
  entry: {
    dev_index: './src/main.js' // 这个对象的键名会传递到下面的'[name].bundle.js'中的 name
  },

  // 输出文件
  output: {
    filename: '[name].bundle.js', // 输出文件名
    path: path.resolve(__dirname, 'dist') // 输出文件目录
  },

  devtool: 'inline-source-map', // 开启source-map

  devServer: {
    static: './dist', // 静态资源目录
    hot: true, // 开启模块热更新
    port: 8080, // 端口号
    open: true, // 自动打开浏览器
    watchFiles: ['./src/index.html'], // 监听文件变化(自动刷新页面)
    client: {
      logging: 'none' // 关闭客户端日志
      // logging: 'error', // 仅显示错误
    }
  },

  plugins: [
    new HtmlWebpackPlugin({
      title: 'template5-dev', // 生成的HTML文件标题
      filename: 'index.html', // 生成的HTML文件名
      template: './src/index.html', // 不配置此项,默认生成index.html;配置此项传递自定义HTML文件
      favicon: path.join(__dirname, './src/img/favicon.ico')
    }),
    new VueLoaderPlugin(), // 添加VueLoaderPlugin
    AutoImport({
      resolvers: [ElementPlusResolver()]
    }),
    Components({
      resolvers: [ElementPlusResolver()]
    })
  ],

  module: {
    rules: [
      {
        test: /\.css$/i, // 匹配css文件
        use: ['style-loader', 'css-loader'] // 使用loader
      },
      {
        test: /\.(png|svg|jpg|jpeg|gif)$/i, // 匹配图片文件
        use: [{ loader: 'url-loader', options: { limit: 6000, esModule: false, name: '[name].[ext]', outputPath: 'images' } }], // 使用loader
        type: 'javascript/auto' // 解决图片打包后路径问题
      },
      {
        test: /\.vue$/,
        loader: 'vue-loader'
      }
    ]
  }
}

完整配置 webpack.prod.js

生产配置

js 复制代码
const path = require('path')
const HtmlWebpackPlugin = require('html-webpack-plugin')
const TerserPlugin = require('terser-webpack-plugin')
const { VueLoaderPlugin } = require('vue-loader')
const AutoImport = require('unplugin-auto-import/webpack')
const Components = require('unplugin-vue-components/webpack')
const { ElementPlusResolver } = require('unplugin-vue-components/resolvers')

module.exports = {
  mode: 'production', // 生产模式

  // 入口文件
  entry: {
    index: './src/main.js' // 这个对象的键名会传递到下面的'[name].bundle.js'中的 name
  },

  // 输出文件
  output: {
    publicPath: './', // 输出文件路径前缀
    filename: '[name].js', // 输出文件名
    path: path.resolve(__dirname, 'dist'), // 输出文件目录
    clean: true // 每次构建前清理dist目录
  },

  plugins: [
    new HtmlWebpackPlugin({
      title: 'template5', // 生成的HTML文件标题
      filename: 'index.html', // 生成的HTML文件名
      template: './src/index.html', // 不配置此项,默认生成index.html;配置此项传递自定义HTML文件
      favicon: path.join(__dirname, './src/img/favicon.ico')
    }),
    new VueLoaderPlugin(), // 添加VueLoaderPlugin
    AutoImport({
      resolvers: [ElementPlusResolver()]
    }),
    Components({
      resolvers: [ElementPlusResolver()]
    })
  ],

  module: {
    rules: [
      {
        test: /\.css$/i, // 匹配css文件
        use: ['style-loader', 'css-loader'] // 使用loader
      },
      {
        test: /\.(png|svg|jpg|jpeg|gif)$/i, // 匹配图片文件
        use: [{ loader: 'url-loader', options: { limit: 6000, esModule: false, name: '[name].[ext]', outputPath: 'images' } }], // 使用loader
        type: 'javascript/auto' // 解决图片打包后路径问题
      },
      {
        test: /\.vue$/,
        loader: 'vue-loader'
      }
    ]
  },

  optimization: {
    minimizer: [
      new TerserPlugin({
        terserOptions: {
          compress: {
            drop_console: true // 移除所有 console.*
          },
          format: {
            comments: false // 移除所有注释
          }
        },
        extractComments: false // 禁止生成独立的注释文件
      })
    ]
  }
}

完整配置 package.json

json 复制代码
{
  "name": "template5",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "dev": "npx webpack serve --config webpack.dev.js",
    "build": "npx webpack --config webpack.prod.js"
  },
  "keywords": [],
  "author": "",
  "license": "ISC",
  "dependencies": {
    "axios": "^1.8.4",
    "element-plus": "^2.9.6",
    "vue": "^3.5.13"
  },
  "devDependencies": {
    "webpack": "^5.98.0",
    "html-webpack-plugin": "^5.6.3",
    "webpack-dev-server": "^5.2.0",
    "style-loader": "^4.0.0",
    "css-loader": "^7.1.2",
    "url-loader": "^4.1.1",
    "vue-loader": "^17.4.2",
    "terser-webpack-plugin": "^5.3.14",
    "unplugin-auto-import": "^0.16.1",
    "unplugin-vue-components": "^0.25.1"
  }
}

完整目录结构

bash 复制代码
src
|- img
|  |- favicon.ico
|- css
|  |- index.css
|- api.js // api文件
|- main.js // 入口文件
|- index.html // html文件
|- App.vue // vue文件
package.json
webpack.dev.js
webpack.prod.js
相关推荐
代码搬运媛6 小时前
Jest 测试框架详解与实现指南
前端
counterxing6 小时前
Agent 跑起来之后,难的是复用、观测和评测
node.js·agent·ai编程
counterxing7 小时前
我把 Codex 里的 Skills 做成了一个 MCP,还支持分享
前端·agent·ai编程
wangqiaowq7 小时前
windows下nginx的安装
linux·服务器·前端
之歆8 小时前
DAY_12JavaScript DOM 完全指南(二):实战与性能篇
开发语言·前端·javascript·ecmascript
发现一只大呆瓜8 小时前
Vite凭什么这么快?3分钟带你彻底搞懂 Vite 热更新的幕后黑手
前端·面试·vite
Maimai108088 小时前
React如何用 @microsoft/fetch-event-source 落地 SSE:比原生 EventSource 更灵活的实时推送方案
前端·javascript·react.js·microsoft·前端框架·reactjs·webassembly
kyriewen10 小时前
产品经理把PRD写成“天书”,我用AI半小时重写了一遍,他当场愣住
前端·ai编程·cursor
humcomm10 小时前
元框架的工作原理详解
前端·前端框架
canonical_entropy10 小时前
Attractor Before Harness: AI 大规模开发的方法论
前端·aigc·ai编程