美文网首页
基于webpack 4.30.0使用总结

基于webpack 4.30.0使用总结

作者: 李牧敲代码 | 来源:发表于2019-04-19 02:24 被阅读0次

之前一直在用各种脚手架构建前端项目,而这些脚手架都已经自带了webpack,虽然自带的默认配置基本也够用,最多也是小改改,就可以进行项目的开发和最终打包部署。但是如果涉及到为了提升各方面的性能进行webpack升级,或者想用webpack打包部署很旧的项目,那么学习webpack就会变得有必要了。

【前言】

webpack有什么用?

  • 基于webpack的前端开发体验非常好。
  • 用webpack打包部署的前端项目性能也比较好。

和gulp的共同点和差异点

共同点:

  1. 都能打包部署前端项目。
  2. 都能提供提供WEB服务和配套的开发环境。

差异点

  1. 侧重和目的不同,webpack是模块打包器,最终目的是为了打包所有资源(注意不一定是打包成一个资源,可以打包成几个包然后按需加载 提高性能)。而gulp是为了执行用户的任务,目的取决于使用它的人(比如做嵌入式开发打包成bin文件)。
  2. 体验不同。
    1. webpack起的服务(webpack-dev-server)中所有前端文件运行在内存中,速度比gulp起的服务(存在磁盘上)要快。
    2. webpack可以实现HMR,而gulp只能实现live reload。
  3. 实际运行代码不同,
    webpack运行的代码是经过自身处理的,而gulp 除了压缩基本还是自己写的代码。

【正文】

正文会按照如下目录总结

  • 开发环境
    • 入口文件
    • 出口文件
    • loader
    • plugin
    • HMR
  • 生产环境
    • 懒加载
    • 压缩
    • 缓存
    • CDN

开发环境

看下的配置:

const path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin'); //生成html文件
const CleanWebpackPlugin = require('clean-webpack-plugin'); //每次build的时候清空之前的目录
const webpack = require('webpack');
const BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin;
const WorkboxPlugin = require('workbox-webpack-plugin');

//path.resolve(...[args])
//从右往左添加路径,最低路径其实拼接取决右边的参数,即使左边写了,也会被忽略,..会忽略左边第一个/后面的路径值,../../会忽略2个,以此类推
//把所有路径定位到项目工程根目录下
function resolve(dir) {
    return path.resolve(__dirname, '..', dir);
}
module.exports = {
    //sourcemap类型
    devtool: 'source-map',
    mode: 'none',
    //入口文件
    entry: {
        main: resolve('./src/main.js')
    },
    //出口文件
    output: {
        path: resolve('dist'),
        // filename: '[name].[chunkhash].js'
        filename: '[name].[hash].js'
    },
    devServer: {
        contentBase: resolve('dist'), //本地服务器所加载的页面所在的目录
        hot: true //HMR开关
    },
    //loader的使用方式
    module: {
        rules: [
            {
                test: /\.css$/,
                use: [
                    'style-loader',
                    'css-loader'
                ]
            },
            {
                test: /\.png|svg|jpg|gif$/,
                use: [
                    'file-loader'
                ]
            }
        ]
    },
    //plugin的使用方式   
    plugins: [
        new CleanWebpackPlugin(),
        new webpack.NamedModulesPlugin(),
        // new webpack.HotModuleReplacementPlugin(),
        new HtmlWebpackPlugin({
            title: 'Cache',
            template: resolve('src/index.html')
        }),
        new webpack.ProvidePlugin({
            jQuery: "jquery"
        }),
        new WorkboxPlugin.GenerateSW({
            // 这些选项帮助 ServiceWorkers 快速启用
            // 不允许遗留任何“旧的” ServiceWorkers
            clientsClaim: true,
            skipWaiting: true
        })
        // new BundleAnalyzerPlugin()
    ]
}

项目目录:


image

package.json:

{
  "name": "test",
  "version": "1.0.0",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1",
    "webpack": "webpack --config ./build/webpack.base.conf.js",
    "server": "webpack-dev-server --config ./build/webpack.base.conf.js",
    "start": "http-server dist"
  },
  "license": "MIT",
  "dependencies": {
    "clean-webpack-plugin": "^2.0.1",
    "css-loader": "^2.1.1",
    "file-loader": "^3.0.1",
    "html-webpack-plugin": "^3.2.0",
    "http-server": "^0.11.1",
    "jquery": "^3.4.0",
    "lodash": "^4.17.11",
    "style-loader": "^0.23.1",
    "webpack": "^4.29.6",
    "webpack-bundle-analyzer": "^3.3.2",
    "webpack-cli": "^3.3.0",
    "webpack-dev-server": "^3.3.1",
    "workbox-webpack-plugin": "^4.3.0"
  }
}

这里需要在webpack脚本中指定配置文件,也就是-- config ./build/webpack.base.conf.js
最后只要在项目工程中运行npm run webpack即可。
PS:
只要打开了HMR开关(hot: true),每个loader会按照webpack提供HMR接口完善各自的HMR。

生产环境

为了达到更好的客户体验,生产环境必须达到最好的性能。而提升性能无非从提高网络传输速度减小资源体积两方面着手。

懒加载

所谓懒加载就是真正需要资源的时候才去获取,而不是一开始就获取所有资源。
在SPA应用中,懒加载典型的应用就是路由懒加载,看下面的vue脚手架的代码(基于webpack)和动图:

import Vue from 'vue'
import Router from 'vue-router'
import Home from './views/Home.vue'

Vue.use(Router)

export default new Router({
  mode: 'history',
  base: process.env.BASE_URL,
  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')//路由懒加载
    }
  ]
})
image

可以看到,当进到about路由的时候,才加载了about.js这个模块。这个得益于webpack的打包技术,让按需加载(懒加载)成为了可能。

压缩

  • UglifyJsPlugin
  • CompressionWebpackPlugin
    这个两个压缩插件分别执行了去注释,合并的常规压缩gzip压缩
    具体使用:
    new UglifyJsPlugin({
      uglifyOptions: {
        compress: {
          warnings: false
        }
      },
      sourceMap: true,
      parallel: true
    }),
    new CompressionWebpackPlugin({
      asset: '[path].gz[query]',
      algorithm: 'gzip',
      test: new RegExp(
        '\\.(' +
       ['js', 'css'].join('|') +
        ')$'
      ),
      threshold: 10240,//超过这个大小开始压缩,单位字节
      minRatio: 0.8
    })
  )

缓存

在webpack4.x之前用的是CommonChunkPlugin,之后移除来了这个插件,用了开箱及用的SplitChunksPlugin,

    optimization: {
        splitChunks: {
          chunks: 'async',//只对异步模块分割
          minSize: 30000,//条件1——代码块的最小尺寸, 大于30kb的模块进行分割
          maxSize: 0,
          minChunks: 1,// 条件2——在分割之前模块的被引用次数
          maxAsyncRequests: 5,// 条件3——按需加载最大并行请求数量
          maxInitialRequests: 3,// 条件4——一个入口最大并行的请求数量
          automaticNameDelimiter: '~',//名称的连接符
          name: true,
          cacheGroups: {
            vendors: {//缓存组
              test: /[\\/]node_modules[\\/]/,//缓存试用的模块
              priority: -10//优先级,越靠近0优先级越高
            },
            default: {//默认缓存的配置
              minChunks: 1,
              priority: -20,
              reuseExistingChunk: true//是否复用模块
            }
          }
        }
      } 

看下main.js



import printNode from './print.js';//包括依赖,大小有300+kb

let getComponent = () => {
    var button2 = document.createElement('button');
    button2.innerHTML = "get component";
    button2.onclick = () => import(/* webpackChunkName: "lodash" */ 'lodash').then(module => {//异步加载的模块
        console.log('lodash loaded')
    })
    return button2;
}
document.body.appendChild(getComponent().button2)

看下打包后的输出结果:

image
可见满足条件1~4的已经组成一个新块(vendors~lodash.abdc43e003ca5d183219.js)了。
这个插件的作用就是分割,提取公共的模块,作为缓存模块。这样只要对于这种经常不变的模块,浏览器只需要缓存在本地不需要向server端频繁请求,从而达到提高性能的目的。

cdn

这玩意就厉害了,特别是对于SPA应用来说,首屏加载就是一个质的飞越!
先说下CDN的概念:
CDN的全称是Content Delivery Network,即内容分发网络。CDN是构建在网络之上的内容分发网络,依靠部署在各地的边缘服务器,通过中心平台的负载均衡、内容分发、调度等功能模块,使用户就近获取所需内容,降低网络拥塞,提高用户访问响应速度和命中率。CDN的关键技术主要有内容存储和分发技术。

下面说下如何在webpack中使用CDN:

在index.html直接引资源

<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width,initial-scale=1.0">
    <title>iwangcx</title>
    <link rel="stylesheet" href="https://unpkg.com/element-ui/lib/theme-chalk/index.css">
  </head>
  <body>
    <div id="app">
    </div>
    <!-- built files will be auto injected -->
    <script src="https://cdn.jsdelivr.net/npm/vue"></script>
    <script src="https://unpkg.com/element-ui/lib/index.js"></script>
    <script src="https://cdn.bootcss.com/jquery/3.4.0/jquery.min.js"></script>
    <script src="https://cdn.bootcss.com/echarts/4.2.1-rc1/echarts.common.min.js"></script>
  </body>
</html>

在webpack配置文件中通过externals排除相应的库

//webpack.base.conf.js
  externals: {
    jQuery: "jquery",
    $: "jquery",
    echarts: "echarts",
    ElementUI: "element-ui",
    Vue: "vue"
  },

看下面的图,是我通过cdn优化前后对比的差距:


2019-04-19_014701.png 优化后的.png image.png image.png

恐怖如斯。。。。

【完】

参考文献

https://www.cnblogs.com/theblogs/p/10472900.html
https://blog.csdn.net/qq_41047322/article/details/81706061
https://segmentfault.com/a/1190000015938570

相关文章

  • 基于webpack 4.30.0使用总结

    之前一直在用各种脚手架构建前端项目,而这些脚手架都已经自带了webpack,虽然自带的默认配置基本也够用,最多也是...

  • webpack整理

    本篇文章基于webpack官网对webpack的基本概念进行的总结。 主要基于 , , , , 几方面阐述,本篇...

  • webpack运行配置(2)

    webpack的使用 webpack-dev-server 这个包 webpack打包 .vue这种文件 总结vu...

  • WebPack + Vue打包流程理解

    1.基于webpack构建vue项目,在不使用laoder或者plugins的情况下,使用webpack命令可以打...

  • vue 使用预编译器 sass

    在基于 webpack 项目模板创建的项目(vue init webpack my-project)中使用 sas...

  • 03. 使用webpack3整合antd3的react项目

    目标 基于webpack3, antd 3, react 16建立一个react项目, 使用webpack方式整合...

  • Vue+Element-UI构建项目

    vue-cli构建基于webpack的项目 使用vue-cli构建项目vue init webpack proje...

  • 2021-08-11 require.context

    实际上是 webpack 的方法,vue 工程一般基于 webpack,所以可以使用require.context...

  • webpack使用总结

    我刚开始使用webpack是一种痛苦体验,我感觉到webpack的各种凌乱。不过等我等我理清思路之后。总的一句...

  • WebPack使用总结

    1、如何支持二级站点发布及部署 参考网址:网站子目录部署VUE webpack 打包资源文件路径的正确引用方式 修...

网友评论

      本文标题:基于webpack 4.30.0使用总结

      本文链接:https://www.haomeiwen.com/subject/perawqtx.html