zoukankan      html  css  js  c++  java
  • webpack 打包编译优化之路

    一、摘要

    从最初的html css js 混合编程,到分离编程。再到用上各种框架 react vue angular , 伴随着框架和模块化的概念铺开,打包编译工具渐渐浮出水面。从2013年开始使用打包编译工具,其也经历了多个更新换代,从最初的grunt -> gulp -> webpack , 还有一些自成体系的,例如 fis , 还有一些比较小众的 rollup , browserify 等。我这里主要分享的是基于 typescript + scss 的webpack3打包编译。

    二、webpack3配置

    2.1 关键配置

    entry

    打包编译入口,可以单入口也可以多入口

    entry : 'xxx/index.tsx',   // 单入口
    entry : ['xxx/index.tsx', 'yyy/index.tsx'],   // 多入口
    entry : {          // 多入口, 并指定编译后的名字
      a: 'xxx/index.tsx',
      b: 'yyy/index.tsx',
    },   // 多入口
    

    output

    path 指定输出路径
    filename 输出的文件名字,可增加 hash 后缀
    publicPath 指定了你在浏览器中用什么地址来引用你的静态文件,它会包括你的图片、脚本以及样式加载的地址,一般用于线上发布以及CDN部署的时候使用。

    {
      output: {
        path: path.resolve(__dirname, 'build'),
        filename: "[name].bundle.[hash:8].js",
        publicPath: "http://localhost:3000/build/"
      },
    }
    

    resolve

    extensions 自动加上文件扩展名,在 import 时 可省略, 比如 import './a.tsx' 可简写成 import './a'
    alias 设置别名,一些常用的库设置别名,可以有效减少import的路径。推荐一个 很好用的插件 alias-resolve-loader 可以把node_modules 依赖的alias 也一并替换。

    resolve: {
      alias: {
        jquery: 'xxxx/xxxx/jqueryjs'
      }
    }
    

    module

    根据你项目使用的语言选择解析loader , 我这里有两种文件 tsx scss ,就分别指定了两种文件的解析loader

    url-loader

    超出 8192 大小的 img 用图片形式,其他采用 base64 码形式打包到js中调用

    module: {
      loaders:[
        { test: /.(png|jpg)$/, loader: 'url-loader?limit=8192&publicPath=./dist/'},
      ]
    }
    

    plugins

    webpack 最强大的就是plugins 生态了,基本你想要的功能都能有现成 plugin 插件直接使用。我们一般常见的插件有

    • webpack.optimize.CommonsChunkPlugin 抽离不常改变的公共组件, 线上环境使用
    • webpack.optimize.UglifyJsPlugin 丑化 js , 线上环境使用
    • ExtractTextPlugin css js 拆分,webpack 默认是把css js 全部打包到一个文件,这样通常会面临加载一个庞大的bundle.js 文件,有这个插件就可以实现 css js 拆分,html 并行加载css js
    • BundleAnalyzerPlugin 分析打包文件大小,可以进一步做文件抽离

    devtool

    可以把错误映射到真实代码中,方便排查错误,生产环境不加

    2.2 真实案例

    真实项目中,一般线下调试和线上是两个版本 webpack 配置

    线下

    线下就做最简单的tsx scss 编译,打包成一个大文件

    const path = require('path'); // 导入路径包
    const webpack = require('webpack');
    
    let config = {
      context: __dirname,
      devtool: "source-map",
      entry: {
        assetManage: "./src/xxx/index.tsx",
      },
    
      output: {
        path: path.resolve(__dirname, 'build'),
        filename: "[name].bundle.js",
        publicPath: "http://localhost:3000/build/"
      },
      resolve: {
        extensions: [".ts", ".tsx", ".js", ".jsx", ".json"]
      },
      // 使用loader模块
      module: {
        loaders: [
          {test: /.scss$/, loader: "style-loader!css-loader!sass-loader"},
          {test: /.tsx?$/, loader: ['react-hot-loader', "ts-loader"]}
        ]
      },
      plugins: [],
    };
    
    module.exports = config;
    

    线上

    线上需要生成文件大小,尽量减少页面加载时间

    const path = require('path'); // 导入路径包
    const webpack = require('webpack');
    
    var ExtractTextPlugin = require('extract-text-webpack-plugin');
    var OptimizeCssAssetsPlugin = require('optimize-css-assets-webpack-plugin');
    var BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin;
    const CompressionPlugin = require("compression-webpack-plugin");
    
    let config = {
      context: __dirname,
      entry: {
        service: "./src/xxx/index.tsx",
        vendor: ['react', 'react-dom'],
      },
      output: {
        path: path.resolve(__dirname, 'build'),
        filename: "[name].bundle.js",
        publicPath: "http://localhost:3000/build/"
      },
      resolve: {
        extensions: [".ts", ".tsx", ".js", ".jsx", ".json"]
      },
      module: {
        loaders: [
          {
            test: /.scss$/,
            use: ExtractTextPlugin.extract({
              fallback: "style-loader",
              use: [{
                loader: "css-loader",
                options: {
                  minimize: true
                }
              }, "sass-loader"]
            })
          },
          {test: /.tsx?$/, loader: ['react-hot-loader', "ts-loader"]}
        ]
      },
      plugins: [
        new webpack.optimize.CommonsChunkPlugin({
          name: 'vendor'
        }),
        new webpack.optimize.UglifyJsPlugin(),
        new ExtractTextPlugin({
          filename: 'css/[name].css',
          allChunks: true
        }),
        new BundleAnalyzerPlugin()
      ],
    };
    
    module.exports = config;
    
    

    三、优化手段

    1. 抽离公共组件 vendor , 拆分基础组件 与 业务逻辑代码

    2. 拆分css至单独文件并压缩

    3. 去除 devtool

    4. 增加 BundleAnalyzerPlugin 分析

    四、其他

    webpack 的替代方案?

    happypack

    rollup

  • 相关阅读:
    【深入学习MySQL】MySQL的索引结构为什么使用B+树?
    【Python爬虫】爬了七天七夜,终于爬出了博客园粉丝数排行榜!
    【BAT面试题系列】面试官:你了解乐观锁和悲观锁吗?
    深入学习MySQL事务:ACID特性的实现原理
    深入学习Redis(5):集群
    深入学习Redis(4):哨兵
    谈谈微信支付曝出的漏洞
    深入学习Redis(3):主从复制
    深入学习Redis(2):持久化
    Spring中获取request的几种方法,及其线程安全性分析
  • 原文地址:https://www.cnblogs.com/huxiaoyun90/p/7685570.html
Copyright © 2011-2022 走看看