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 [email protected] [email protected] --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
相关推荐
关山月几秒前
React 中的 SSR 深度探讨
前端
yzhSWJ35 分钟前
vue设置自定义logo跟标题
前端·javascript·vue.js
vvilkim1 小时前
Vue.js 中的 Tree Shaking:优化你的应用性能
前端·javascript·vue.js
杨超越luckly1 小时前
HTML应用指南:利用GET请求获取猫眼电影日票房信息——以哪吒2为例
前端·数据挖掘·数据分析·html·猫眼
狼性书生1 小时前
uniapp 实现的下拉菜单组件
前端·uni-app·vue·组件·插件
浪裡遊1 小时前
uniapp中的vue组件与组件使用差异
前端·vue.js·uni-app
风无雨2 小时前
react 中 key 的使用
前端·react.js·前端框架
shix .2 小时前
某视频的解密下载
服务器·前端·音视频
吃杠碰小鸡2 小时前
css-grid布局
前端·css
消失的旧时光-19432 小时前
kotlin 内联函数 inline
java·前端·kotlin