关于webpack代码拆分的解析

网络编程 JavaScript javascript技巧 分类:[default] 更新日期: 2017-08-03
本篇文章主要介绍了关于webpack代码拆分的解析,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧

最近在学习VUE的时候接触到了webpack,今天就留个小笔记,介绍一下webpack代码拆分

如果利用 webpack 将项目中的所有代码打包在一起,很多时候是不适用的,因为代码中有些东西我们总是希望将其拆分出来。比如:

  1. 样式表,希望利用 link 标签引入
  2. 使用概率较低的模块,希望后期需要的时候异步加载
  3. 框架代码,希望能利用浏览器缓存下部分不易变动的代码

下面是我在阅读 webpack 的官方文档时候,记录的一些笔记,部分地方使用了自己的话来讲,力图让它显得更易懂。

按需加载拆分

webpack 可以帮助我们将代码分成不同的逻辑块,在需要的时候加载这些代码。

使用 require.ensure() 来拆分代码

require.ensure() 是一种使用 CommonJS 的形式来异步加载模块的策略。在代码中通过 require.ensure([<fileurl>]) 引用模块,其使用方法如下:

extract text plugin for webpack 2

拆分业务代码与框架代码

通常一个 web 应用都会引用若干第三方库,这些第三方库通常比较稳定不会经常变动,但是如果将业务代码和框架代码打包在了一起,这样业务代码每次变动打包得到的结果都会变动,及时只改变了一个字符,浏览器也无法利用缓存,必须全部重新加载。因此,何不将第三方库单独打包在一起呢?

这里举个案例,一个 react 项目中使用了 react react-dom 这两个包,我希望将他们打包在一起,将业务代码打包在一起。

下面一步一步来:

1. 安装 react 和 react-dom:

npm i react react-dom --save

2. 配置 entry,output 和 loader

先使用单入口,让代码工作起来。另外因为使用了 react 所以要使用 babel-loader 来加载 js

// webpack.config.js

module.exports = {
  entry: 'index.js',
  output: {
    path: 'build/',
    filname: '[name]@[chunkhash].js'
  },
  module:{
    loaders:[{
      test: /\.js$/,
      exclude: /node_modules/,
      loader: 'babel'
    }]
  }
}

3. 编写业务代码

index.js:

import React from 'react';
import ReactDOM from 'react-dom';


var Hello = React.createClass({
  render: function() {
    return <div>Hello {this.props.name}</div>;
  }
});

ReactDOM.render(<Hello name={'world'} />, document.getElementById('app'));

index.html:

<div ></div>
<!--entry 为一个字符串,这个 chunk 的名字会是 main, 因此这里引入 main.js -->
<script src="build/main.js"></script>

启动 webpack-dev-server,打开浏览器这个时候应该能在页面上看到 hello world,这说明工作正常。

4. 拆分框架代码

为了拆分框架代码,我们需要增加一个入口,在这个入口中要包含 react react-dom

module.exports = {
  entry: {
    main: 'index.js',
    vendor: ['react', 'react-dom']
  }
  //...
}

单单像上面这样配置,打包后会得到 main.js 和 vendor.js,但会发现在 main.js 中依然包含了 react 和 react-dom 的代码,这是因为指定了入口后,webpack 就会从入口文件开始讲整个依赖打包进来,index.js 中引用了 react 和 react-dom 自然会被打包进去。要想达到之前所说的那个效果,还需要借助一个插件 —— CommonsChunkPlugin

5. 使用 CommonsChunkPlugin

这个插件的功能是将多个打包结果中公共的部分抽取出来,作为一个单独的文件。它符合目前的场景,因为 main.js vendor.js 中存在一份公共的代码,那就是 vendor.js 中的内容。(这个说法并不准确,这里只是指 react 和 react-dom 都被打包进了这两个文件)

let webpack = require('webpack');

module.exports = {
  entry: {
    main: 'index.js',
    vendor: ['react', 'react-dom']
  },
  //...

  plugins: [
    new webpack.optimize.CommonsChunkPlugin({
      name: 'vendor' // 指定一个希望作为公共包的入口
    })
  ]
}

再进行打包,这个时候会发现 main.js 中的代码不在包含 react 的代码了。看似实现了我们的需求,但真实应用下并没有这么简单,在实际项目中 js 脚本通常都会给添加一个 MD5 的 hash 在后面,形如 [email protected].js 这样每次打包后,如果文件内容变了,后面的 hash 也会变动。就以上场景,会发现当我们修改了业务代码后,得到的 hash 是不同的,因此每次都会得到两个不同的打包结果。业务代码改变了,拆分出来的框架包也变了,这显然不符合初衷 —— 利用浏览器缓存。

这是因为 webpack 在打包的时候会产生一些运行时代码,比如 __webpack_require__ webpackJsonp 等等,这些函数是用来帮助 webpack 完成模块加载等功能的,业务代码的改变会导致业务代码打包后的 hash 值改变,而在 webpack 的运行时代码中实际上是保存了打包后的结果的文件名的,因为它在异步加载模块的时候需要用到。因此,下面需要做的是将 webpack 的运行时代码拆分出来。

修改 plugins 如下,将 name 修改为 names,并增加一个 init 的包名,执行打包,会发现 webpack 的运行时代码都被入该包内。

plugins: [
  new webpack.optimize.CommonsChunkPlugin({
    names: ['vendor', 'init']
  })
]

这样以来,修改了业务代码后,vendor 因为只引用了 react 和 react-dom 因此,业务代码的改变不会改变 vendor 这个包的内容,hash 也保持不变。但,也仅仅如此 如果你引用了其他模块,webpack 收集依赖的时候会给每个模块编一个号,引入其他模块会导致模块数改变,也就会导致编号改变,这个时候打包出来的 vendor 还是会改变。

那么到底该如何解决这个问题呢?在官方文档上没有找到解决方案。后面我会继续探索这一问题,找到解决方案后会及时更新到这里,如果你有解决方案,还请不吝赐教,谢谢。

希望本文所述对你有所帮助,webpack代码拆分内容就给大家介绍到这里了。希望大家继续关注我们的网站!


> 本站内容系网友提交或本网编辑转载,其目的在于传递更多信息,并不代表本网赞同其观点和对其真实性负责。如涉及作品内容、版权和其它问题,请及时与本网联系,我们将在第一时间删除内容!

相关文章
  • MongoDB的Master-Slave主从模式配置及主从复制要点解析
    主从复制是数据库运维中一种常见的备份方式,这里我们来看一下MongoDB的Master-Slave主从模式配置及主从复制要点解析,需要的朋友可以参考下主从配置mongodb的master-slave模式配置方式如下1.keyFile生成key_file openssl rand -base64 741 > mongo_key 将mongo_key 分别 ...
  • PHP生成静态HTML文档实现代码
    这篇文章主要为大家详细介绍了PHP生成静态HTML文档实现代码,将数据库中的文章数据生成单个的HTML文档原理,感兴趣的小伙伴们可以参考一下利用PHP,将数据库中的文章数据生成单个的HTML文档.首先,有利于搜索引擎的收录.其次,避免数据库中的字段暴露在地址栏上,更安全. 给出代码: <?php //引入数据库配置文件 include( dirname ...
  • js选择器全面解析
    下面小编就为大家带来一篇js选择器全面解析.小编觉得挺不错的,现在就分享给大家,也给大家做个参考.一起跟随小编过来看看吧原生JS选择器有getElementById.getElementsByName.getElementsByTagName和getElementsByClassName这四个,下面我就一个一个介绍这四个选择器的用法. 1.getElemen ...
  • php好代码风格的阶段性总结
    这篇文章主要介绍了php好代码风格,阶段性总结了php程序设计中变量.函数.参数的相关使用注意事项与编程技巧,具有一定参考借鉴价值,需要的朋友可以参考下本文总结了php好代码的风格,分享给大家供大家参考,具体如下: 1.避免使用魔数 if($age<18){ } 这个18不太明白为什么要这样子. 可以将28定义在一个变量里面,这个变量命名表明了这个值的 ...
  • 将PHP的session数据存储到数据库中的代码实例
    这里我们将分享两个将PHP的session数据存储到数据库中的代码实例,分别针对PostgreSQL与MySQL,需要的朋友可以参考下一个开发环境有多个网站,需要使用不同的session,解决方案很多.不过这次也高大上一把,用数据库存,方便以后扩展. PostgreSQL版首先是数据库的部分 --drop table php_session create u ...
  • 提高代码可读性的十大注释技巧分享
    这篇文章主要介绍了提高代码可读性的十大注释技巧,详细分析了编程开发中常用的代码注释方法,需要的朋友可以参考下本文讲述了提高代码可读性的十大注释技巧.分享给大家供大家参考,具体如下: 很多程序员在写代码的时候往往都不注意代码的可读性,让别人在阅读代码时花费更多的时间.其实,只要程序员在写代码的时候,注意为代码加注释,并以合理的格式为代码加注释,这样就方便别人查 ...
猜你喜欢