webpack 打包优化

webpack 打包优化

速度优化

  • 优化图片
使用 url-loader 优化, 将小图片转化成base64压缩,防止小图片太多请求次数太多。
:下载 url-loader
     npm install -D url-loader
2: 配置
   在 webpack.prod.conf.js 文件夹中配置
     module: {
      rules: [{
         test: /\.(png|svg|jpg|gif)$/,
         use: [{
           loader: 'url-loader', // 优化小图片过多造成请求数太多
           options: {
             limit: 8192, // 如果图片小于 8192 bytes 就直接 base64 内置到模板,否则才拷贝
             outputPath: 'img/'
           } 
         }]
      },
  • 分离 css 文件并压缩 css 文件

使用 extract-text-webpack-plugin 插件将css文件分离出来。为了使项目加载时候尽早优先加载css样式,也为了解决js文件体积过大的问题

1: 下载 extract-text-webpack-plugin
     npm  install  -D  extract-text-webpack-plugin
2: 配置
   在 webpack.prod.conf.js 文件夹中配置
    1> 引入 
         const ExtractTextPlugin = require("extract-text-webpack-plugin")
    2> 配置分离 css 文件
         plugins: [
               new ExtractTextPlugin("css/styles.css"), // 把抽离出来的 css 文件打包到 styles.css 文件中
         ],
        module: {
         rules: [ {
           test: /\.css$/,
           use: ExtractTextPlugin.extract({
                  fallback: "style-loader",
                  use: {
                        loader: 'css-loader',
                       options: {
                            minimize: true
                       }
                 }
          })
       },
     } ]
  3> 配置压缩css (直接配置 css-loader 属性的选项)
 module: {
    rules: [
          {
            test: /\.css$/,
            use: ExtractTextPlugin.extract({
                fallback: "style-loader",
               //这个地方配置一个对象,添加一个属性进行压缩css文件
               use: {
                   loader: 'css-loader',
                  options: {
                    minimize: true   // 配置minimize 值为true,压缩css 文件
                  }
              }
           })
      },
  • 压缩js 文件
使用 uglifyjs-webpack-plugin 将js压缩,减少打包后的 vendor.js , bundle.js 等js的文件大小
 1: 下载 uglifyjs-webpack-plugin
         npm install -D uglifyjs-webpack-plugin
    2: 配置
        在webpack.prod.conf.js 文件夹中配置
        1> 引入
           const UglifyJsPlugin = require('uglifyjs-webpack-plugin')
        2> 配置
           plugins: [
                new UglifyJsPlugin(), // 压缩 JavaScript
           ],
  • 缩小文件匹配范围(include/exclude)
module: {
  rules: [
    {
      test: /\.js$/,
      use: 'babel-loader',
      exclude: /node_modules/, // 排除不处理的目录
      include: path.resolve(dirname, 'src') // 精确指定要处理的目录
    }
  ]
}
  • resolve优化配置
2.1 优化模块查找路径 resolve.modules
Webpack的resolve.modules配置模块库(即 node_modules)所在的位置,在 js 里出现 import ‘vue’ 这样不是相对、也不是绝对路径的写法时,会去 node_modules 目录下找。但是默认的配置,会采用向上递归搜索的方式去寻找,但通常项目目录里只有一个 node_modules,且是在项目根目录,为了减少搜索范围,可以直接写明 node_modules 的全路径;同样,对于别名(alias)的配置,亦当如此:
const path = require('path');
function resolve(dir) { // 转换为绝对路径
  return path.join(dirname, dir);
}
resolve: {
  modules: [ // 优化模块查找路径
    path.resolve('src'),
    path.resolve('node_modules') // 指定node_modules所在位置 当你import 第三方模块时 直接从这个路径下搜索寻找
  ]
}
配置好src目录所在位置后,由于util目录是在src里面 所以可以用下面方式引入util中的工具函数
// main.js
import dep1 from 'util/dep1';
import add from 'util/add';
2.2 resolve.alias 配置路径别名
创建 import 或 require 的路径别名,来确保模块引入变得更简单。配置项通过别名来把原导入路径映射成一个新的导入路径 此优化方法会影响使用Tree-Shaking去除无效代码。
例如,一些位于 src/ 文件夹下的常用模块
alias: {
 Utilities: path.resolve(dirname, 'src/utilities/'),
 Templates: path.resolve(dirname, 'src/templates/')
}
现在,替换「在导入时使用相对路径」这种方式,就像这样:
import Utility from '../../utilities/utility';
你可以这样使用别名:
import Utility from 'Utilities/utility';
resolve: {
  alias: { // 别名配置 通过别名配置 可以让我们引用变的简单
    'vue$': 'vue/dist/vue.common.js', // $表示精确匹配
    src: resolve('src') // 当你在任何需要导入src下面的文件时可以 import moduleA from 'src/moduleA' src会被替换为resolve('src') 返回的绝对路径 而不需要相对路径形式导入
  }
}
也可以在给定对象的键后的末尾添加 $,以表示精准匹配:
alias: {
  util$: resolve('src/util/add.js')
}
这将产生以下结果:
import Test1 from 'util'; // 精确匹配,所以 src/util/add.js 被解析和导入
import Test2 from 'util/dep1.js'; // 精确匹配,触发普通解析 util/dep1.js
  • HappyPack HappyPack是让webpack对loader的执行过程,从单一进程形式扩展为多进程模式,也就是将任务分解给多个子进程去并发的执行,子进程处理完后再把结果发送给主进程。从而加速代码构建 与 DLL动态链接库结合来使用更佳。
npm i happypack@next -D
const HappyPack = require('happypack');
const os = require('os'); // node 提供的系统操作模块
 // 根据我的系统的内核数量 指定线程池个数 也可以其他数量
const happyThreadPool = HappyPack.ThreadPool({size: os.cpus().lenght})
module: {
  rules: [
    {
      test: /\.js$/,
      use: 'happypack/loader?id=babel',
      exclude: /node_modules/,
      include: path.resolve(dirname, 'src')
    }
  ]
},
plugins: [
  new HappyPack({ // 基础参数设置
    id: 'babel', // 上面loader?后面指定的id
    loaders: ['babel-loader?cacheDirectory'], // 实际匹配处理的loader
    threadPool: happyThreadPool,
    // cache: true // 已被弃用
    verbose: true
  });
]
  • Tree Shaking
剔除JavaScript中用不上的代码。它依赖静态的ES6模块化语法,例如通过impot和export导入导出

大小优化


大小优化
1.CommonsChunk
前端构建项目中,为了提高打包效率,往往将第三库与业务逻辑代码分开打包,因为第三方库往往不需要经常打包更新。webpack建议使用CommonsChunk 来单独打包第三方库:

module.exports = {
    entry: {
        vendor: ['react','react-dom'],
        app: "./main",
    },
    output: {
        path: './build',
        filename: '[name].js',
        library: '[name]_library'
    },
    plugins: [
        new CommonsChunkPlugin({
            name: "vendor",
        }),
    ]
};
CommonsChunk虽然可以减少包的大小,但存在问题是:即使代码不更新,每次重新打包,vendor都会重新生成,不符合我们分离第三方包的初衷。

2.Externals
相比于前者,webpack 提供Externals的方法,可以通过外部引用的方法,引入第三方库: index.html

<script src="https://code.jquery.com/jquery-3.1.0.js"></script>
1
webpack.config.js

module.exports = {
   externals: {
     jquery: 'jQuery'
   }
};
业务逻辑,如index.js
import $ from 'jquery';
$('.my-element').animate(...);
webpack打包时,发现jquery定义在externals,则不会打包jquery代码。由于不需要打包jquery,所以也减少打包时间。 不过externals虽然解决了外部引用问题,但是无法解决以下问题:
import xxx from 'react/src/xx';
webpack遇到此问题时,会重新打包react代码。 参考:https://gold.xitu.io/entry/57996222128fe1005411c649

**3.DLL & DllReference**
相比于前者,通过前置这些依赖包的构建,来提高真正的build和rebuild构建效率。也就是说只要第三方库没有变化,之后的每次build都只需要去打包自己的业务代码,解决Externals多次引用问题。 webpack通过webpack.DllPlugin与webpack.DllReferencePlugin两个内嵌插件实现此功能。
1、新建webpack.dll.config.js
const webpack = require('webpack');
module.exports = {
    entry: {
        bundle: [
            'react',
            'react-dom',
            //其他库
            ],
    },
    output: {
        path: './build',
        filename: '[name].js',
        library: '[name]_library'
    },
    plugins: [
        new webpack.DllPlugin({
            path: './build/bundle.manifest.json',
            name: '[name]_library',
        })
    ]
};

webpack.DllPlugin选项:
path:manifest.json文件的输出路径,这个文件会用于后续的业务代码打包;
name:dll暴露的对象名,要跟output.library保持一致;
context:解析包路径的上下文,这个要跟接下来配置的 webpack.config.js 一致。
运行:
npm run webpack-dll
生成两个文件,一个是打包好的bundlejs,另外一个是bundle.mainifest.json,大致内容如下:

{
  "name": "bundle_library",
  "content": {
    "./node_modules/react/react.js": 1,
    "./node_modules/react/lib/React.js": 2,
    "./node_modules/process/browser.js": 3,
    "./node_modules/object-assign/index.js": 4,
    "./node_modules/react/lib/ReactChildren.js": 5,
    "./node_modules/react/lib/PooledClass.js": 6,
    "./node_modules/react/lib/reactProdInvariant.js": 7,
    //其他引用
}

2、配置webpack.config.js
const webpack = require('webpack');
var path = require('path');
module.exports = {
  entry: {
    main: './main.js',
  },
  output: {
    path: path.join(__dirname, "build"),
    publicPath: './',
    filename: '[name].js'
  },
  module: {
    loaders:[
      { test: /\.(png|jpg)$/, loader: 'url-loader?limit=8192'},
      {
        test: /\.jsx?$/,
        loaders: ['babel-loader?presets[]=es2015&presets[]=react'],
        include: path.join(__dirname, '.')
      }
    ]
  },
  plugins: [
     new webpack.DllReferencePlugin({
      context: '.',
      manifest: require("./build/bundle.manifest.json"),
        }),
  ]
};
webpack.DllReferencePlugin的选项中:
context:需要跟之前保持一致,这个用来指导webpack匹配manifest.json中库的路径;
manifest:用来引入刚才输出的manifest.json文件。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值