webpack 打包优化 体验+++

本文详细介绍了webpack的配置和优化技巧,包括通过webpack.config.js进行配置、核心概念(入口、输出、loader、插件、模式)、Devtool的配置、优化策略(如查看打包时间、隐藏源码、开启CDN、代码分割、路由懒加载和GZIP优化)等,旨在提升前端项目的打包效率和用户体验。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

webpack

在这里插入图片描述

webpack 是一个模块打包器,主要目的是在浏览器上打包 JavaScript 文件。从图中我们可以看出,Webpack 可以将多种静态资源 js、css、less 转换成一个静态文件,减少了页面的请求。

特性

  • 打包 CommonJs, AMD, ES6 modules, CSS, Images, JSON, Coffeescript, LESS,等模块
  • 可创建单个或多个按需加载的块,以减少初始加载时间
  • 在编译期间会解决依赖关系,减少了运行时的大小

初体验

  1. 全局安装 webpack

    npm install -g webpack webpack-cli // window 
    sudo npm install -g webpack webpack-cli// mac 或者 linux
    
  2. 新建目录

mkdir app // 新建app目录
  1. 在app目录下,新建 index.htmlindex.jsapp.js文件 填入以下内容

index.html

<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Document</title>
</head>
<body>
    
</body>
<script src="./dist/main.js"></script>
</html>

index.js

// 引入 app 组件
import app from "./app"
// 运行app 组件
app();

app.js

// 导出模块
export default function(){
    document.write("webpack 例子 lol!");
}
  1. 在app目录下运行 webpack
    在这里插入图片描述

  2. 默认会在app目录下生成 dist/main.js 文件
    在这里插入图片描述

  3. 打开 app 目录下的 index.html 文件,可以看到以下结果

在这里插入图片描述

通过 webpack.config.js 进行配置

新建 webpack.config.js 文件,填入以下内容

const path = require("path")
module.exports = {
    mode:"development",
    entry:"./index.js",
    output:{
        path:path.resolve(__dirname,"dist"),
        filename:"bundle.js"
    }
}

运行

webpack

此时会在 当前目录下生成 dist/bundle.js 文件

核心概念

入口

**入口起点(entry point)**指示 webpack 应该使用哪个模块,来作为构建其内部 依赖图(dependency graph) 的开始。例如:

webpack.config.js

module.exports = {
  entry: './path/to/my/entry/file.js'
};

输出(output)

output 属性告诉 webpack 在哪里输出它所创建的 bundle,以及如何命名这些文件。主要输出文件的默认值是 ./dist/main.js,其他生成文件默认放置在 ./dist 文件夹中。

你可以通过在配置中指定一个 output 字段,来配置这些处理过程:

const path = require('path');

module.exports = {
  entry: './path/to/my/entry/file.js',
  output: {
    path: path.resolve(__dirname, 'dist'),
    filename: 'my-first-webpack.bundle.js'
  }
};

loader

webpack 只能理解 JavaScript 和 JSON 文件,这是 webpack 开箱可用的自带能力。loader 让 webpack 能够去处理其他类型的文件,并将它们转换为有效 模块,以供应用程序使用,以及被添加到依赖图中。

在更高层面,在 webpack 的配置中,loader 有两个属性:

  1. test 属性,识别出哪些文件会被转换。
  2. use 属性,定义出在进行转换时,应该使用哪个 loader。

例如使用 css-loader 实现样式的加载

  1. 本地安装依赖
npm install --save-dev style-loader css-loader
  1. 配置 webpack.config.js 文件
const path = require("path")
module.exports = {
    mode:"development",
    entry:"./index.js",
    output:{
        path:path.resolve(__dirname,"dist"),
        filename:"bundle.js"
    },
    module:{
        rules:[
            {
                test: /\.css$/,
                use: [ 'style-loader', 'css-loader' ]
            }
        ]
    }
}

index.js

// 引入 app 组件
import app from "./app"
// 运行app 组件
app();

index.css

.red{
    color:red
}

App.js

// 导出模块
import "./index.css"
export default function(){
    document.write("<h1 class='red'>webpack 例子 lol!</h1>");
}
index.html

<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Document</title>
</head>
<body>
</body>
<script src="./dist/bundle.js"></script>
</html>

插件(plugins)

loader 被用于转换某些类型的模块,而插件则可以用于执行范围更广的任务。插件的范围包括,从打包优化和压缩,一直到重新定义环境中的变量。

想要使用一个插件,你只需要 require() 它,然后把它添加到 plugins 数组中。多数插件可以通过选项(option)自定义。你也可以在一个配置文件中因为不同目的而多次使用同一个插件,这时需要通过使用 new 操作符来创建它的一个实例。

例子,该例子会将生成的 js 文件自动注入到 html文件中

  1. 本地安装插件和webpack
npm install --save-dev html-webpack-plugin // html 插件
npm install --save-dev webpack webpack-cli
npm install --save-dev style-loader css-loader

  1. Webpack.config.js 配置文件
const path = require("path")
var HtmlWebpackPlugin = require('html-webpack-plugin');
module.exports = {
    mode: "development",
    entry: "./index.js",
    output: {
        path: path.resolve(__dirname, "dist"),
        filename: "bundle.js"
    },
    module: {
        rules: [
            {
                test: /\.css$/,
                use: ['style-loader', 'css-loader']
            }
        ]
    },
    plugins: [new HtmlWebpackPlugin()]
}
  1. 添加以下文件

index.js

// 引入 app 组件
import app from "./app"
// 运行app 组件
app();

app.js

// 导出模块
import "./index.css"
export default function(){
    document.write("<h1 class='red'>webpack 例子 lol!</h1>");
}

index.css

.red{
    color:red
}
  1. 运行 webpack

  2. 默认在当前目录下生成 dist/html 并自动注入生成的js文件

在这里插入图片描述

模式(mode)

通过选择 development, productionnone 之中的一个,来设置 mode 参数,你可以启用 webpack 内置在相应环境下的优化。其默认值为 production

module.exports = {
  mode: 'production'
};

Devtool

此选项控制是否生成,以及如何生成 source map。

例如如下所示的的 dev-tool

const path = require("path")
var HtmlWebpackPlugin = require('html-webpack-plugin');
module.exports = {
    devtool:"eval-source-map",
    mode: "development",
    entry: "./index.js",
    output: {
        path: path.resolve(__dirname, "dist"),
        filename: "bundle.js"
    },
    module: {
        rules: [
            {
                test: /\.css$/,
                use: ['style-loader', 'css-loader']
            }
        ]
    },
    plugins: [new HtmlWebpackPlugin()]
}

生成代码之后,打开 chrome 控制台,可以看到如下所示目录

在这里插入图片描述

Devtool 的配置选项

devtool构建速度重新构建速度生产环境品质(quality)
(none)非常快速非常快速yes打包后的代码
eval非常快速非常快速no生成后的代码
eval-cheap-source-map比较快快速no转换过的代码(仅限行)
eval-cheap-module-source-map中等快速no原始源代码(仅限行)
eval-source-map比较快no原始源代码
eval-nosources-source-map
eval-nosources-cheap-source-map
eval-nosources-cheap-module-source-map
cheap-source-map比较快中等yes转换过的代码(仅限行)
cheap-module-source-map中等比较慢yes原始源代码(仅限行)
inline-cheap-source-map比较快中等no转换过的代码(仅限行)
inline-cheap-module-source-map中等比较慢no原始源代码(仅限行)
inline-source-mapno原始源代码
inline-nosources-source-map
inline-nosources-cheap-source-map
inline-nosources-cheap-module-source-map
source-mapyes原始源代码
hidden-source-mapyes原始源代码
hidden-nosources-source-map
hidden-nosources-cheap-source-map
hidden-nosources-cheap-module-source-map
hidden-cheap-source-map
hidden-cheap-module-source-map
nosources-source-mapyes无源代码内容
nosources-cheap-source-map
nosources-cheap-module-source-map

对于开发环境

eval-source-map - 每个模块使用 eval() 执行,并且 source map 转换为 DataUrl 后添加到 eval() 中。初始化 source map 时比较慢,但是会在重新构建时提供比较快的速度,并且生成实际的文件。行数能够正确映射,因为会映射到原始代码中。它会生成用于开发环境的最佳品质的 source map

对于生产环境

(none)(省略 devtool 选项) - 不生成 source map。这是一个不错的选择。

优化

查看各个环节的打包时间

安装 speed-measure-webpack-plugin

npm install --save-dev speed-measure-webpack-plugin

然后在vue.config.js文件里面添加如下配置

// vue.config.js
const SpeedMeasurePlugin = require("speed-measure-webpack-plugin");
const smp = new SpeedMeasurePlugin();
module.exports = {
    configureWebpack: smp.wrap({
        plugins: [
        ]
    })
}

运行

npm run build

可以看到各个环节的打包时间

在这里插入图片描述

优化配置

隐藏源码

在 根目录下的 vue.config.js 文件中添加如下配置

 module.exports = {
    productionSourceMap: false
} 


开启CDN加速


module.exports = {
    chainWebpack: config => {
       // 提取公用代码, 使用免费的cdn资源
        config.externals({
            vue: 'Vue',
            vuex: 'Vuex',
            'vue-router': "VueRouter",
            'element-ui': "'element-ui'",
        })


    }
}
index.html 页面填入相应的CDN地址
<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="utf-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width,initial-scale=1.0">
  <link rel="icon" href="<%= BASE_URL %>favicon.ico">
  <title><%= htmlWebpackPlugin.options.title %></title>
  <!-- 引入样式 -->
  <link rel="stylesheet" href="https://unpkg.com/element-ui/lib/theme-chalk/index.css">
</head>

<body>
  <noscript>
    <strong>We're sorry but <%= htmlWebpackPlugin.options.title %> doesn't work properly without JavaScript enabled.
      Please enable it to continue.</strong>
    </noscript>
    <div id="app"></div>
    <!-- built files will be auto injected -->
    <script src="https://cdn.bootcdn.net/ajax/libs/vue/2.6.0/vue.runtime.min.js"></script>
    <script src="https://unpkg.com/vuex@2.0.0/dist/vuex.min.js"></script>
    <script src="https://unpkg.com/vue-router@3.3.4/dist/vue-router.min.js"></script>
    <!-- 引入组件库 -->
    <script src="https://unpkg.com/element-ui/lib/index.js"></script>
  </body>

</html>

代码最小化处理

module.exports = {
    chainWebpack: config => {
      // 代码最小化处理
			  config.optimization.minimize(true);
    }
}

在这里插入图片描述

使用splitChunks进行代码分割

        // 使用splitChunks进行代码分割
        config.optimization.splitChunks({
            chunks: 'all',
            cacheGroups: {
                libs: {
                    name: 'my-chunk-libs',
                    test: /[\\/]node_modules[\\/]/,
                    priority: 10,
                    chunks: 'initial' // only package third parties that are initially dependent
                }
            }
        })

在这里插入图片描述

路由懒加载


const routes = [
  {
    path: '/',
    name: 'Home',
    component: Home
  },
  {
    path: '/about',
    name: 'About',
    // route level code-splitting
    // this generates a separate chunk (about.[hash].js) for this route
    // which is lazy-loaded when the route is visited.
    component: () => import(/* webpackChunkName: "about" */ '../views/About.vue')
  }
]

或者

const Foo = () => import(/* webpackChunkName: "group-foo" */ './Foo.vue')
const Bar = () => import(/* webpackChunkName: "group-foo" */ './Bar.vue')
const Baz = () => import(/* webpackChunkName: "group-foo" */ './Baz.vue')

Webpack 会将任何一个异步模块与相同的块名称组合到相同的异步块中。

在这里插入图片描述

开启GZIP优化

gzip压缩

如果后台有对前端的代码进行gzip压缩的话,那么就不需要进行压缩了,后台自己配置就可以。

完整配置

vue.config.js

const SpeedMeasurePlugin = require("speed-measure-webpack-plugin");
const smp = new SpeedMeasurePlugin();

module.exports = {
    publicPath:"/dist", // 设置应用的目录 可以改成 app myapp 等 对应的是服务器下的目录
    productionSourceMap: false, // 生成生产版本的时候 关闭 源码映射
    configureWebpack: smp.wrap({
        // https://webpack.js.org/configuration/devtool/#development
        // 修改source map
        // devtool:"eval-source-map",
        plugins: [
        ]
    }),
    chainWebpack: config => {
        // 代码最小化处理
        config.optimization.minimize(true);
        // 使用splitChunks进行代码分割
        config.optimization.splitChunks({
            // // include all types of chunks
            chunks: 'all',
            cacheGroups: {
                libs: {
                    name: 'my-chunk-libs',
                    test: /[\\/]node_modules[\\/]/,
                    priority: 10,
                    chunks: 'initial' // only package third parties that are initially dependent
                }
            }
        })
        // 提取公用代码, 使用免费的cdn资源
        config.externals({
            vue: 'Vue',
            vuex: 'Vuex',
            'vue-router': "VueRouter",
             'element-ui': "'element-ui'",
        })
    }
}


index.html

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

<head>
  <meta charset="utf-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width,initial-scale=1.0">
  <link rel="icon" href="<%= BASE_URL %>favicon.ico">
  <title><%= htmlWebpackPlugin.options.title %></title>
  <!-- 引入样式 -->
  <link rel="stylesheet" href="https://unpkg.com/element-ui/lib/theme-chalk/index.css">
</head>

<body>
  <noscript>
    <strong>We're sorry but <%= htmlWebpackPlugin.options.title %> doesn't work properly without JavaScript enabled.
      Please enable it to continue.</strong>
    </noscript>
    <div id="app"></div>
    <!-- built files will be auto injected -->
    <script src="https://cdn.bootcdn.net/ajax/libs/vue/2.6.0/vue.runtime.min.js"></script>
    <script src="https://unpkg.com/vuex@2.0.0/dist/vuex.min.js"></script>
    <script src="https://unpkg.com/vue-router@3.3.4/dist/vue-router.min.js"></script>
    <!-- 引入组件库 -->
    <script src="https://unpkg.com/element-ui/lib/index.js"></script>
  </body>

</html>

线上代码地址

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值