webpack

webpack打包原理是根据文件间的依赖关系对其进行静态分析,将这些模块按指定规则生成静态资源,当webpack处理程序时,它会递归地构建一个依赖关系图,将所有这些模块打包成一个或多个bundle。
webpack有两种组织模块的依赖方式,同步、异步。异步依赖将作为分割点,形成一个新的块;在优化了依赖树之后,每一个异步区块都将作为一个文件被打包。
webpack有一个智能解析器,几乎可以处理任何第三方库。无论它们的模块形式是CommonJs、AMD还是普通的JS文件;甚至在加载依赖的时候,允许使用动态表require("、/templates/" + name+ “、jade”)

webpack主要分为四块:entry、output、loader、plugin
loader:是一个转换器,将A文件进行编译成B文件, 比如A.less转换为A.css,单纯的文件转换过程。webpack本身只支持js和 json文件格式,对于其他文件需要通过loader将其转换为commonJS规范的文件后,webpack才能解析到。
plugin: 是一个扩展器,它丰富了webpack本身,针对是loader结束后,webpack打包的整个过程中,它并不直接操作文件,而是基于事件机制本身,会监听webpack打包过程中的某些节点,执行广泛的任务。

module,chunk 和 bundle 其实就是同一份逻辑代码在不同转换场景下的取了三个名字:

我们直接写出来的是 module,webpack 处理时是 chunk,最后生成浏览器可以直接运行的 bundle。

  • Entry

    入口起点指示webpack应该使用哪个模块,来作为构建其内部依赖图的开始。进入入口起点后,webpack会找出有哪些模块和库是入口起点(直接和间接)依赖的。每个依赖项随即被处理,最后输出到称之为bundles的文件中。
    默认值是./src/index.js,可通过配置属性,来指定一个或多个不同的入口起点

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

	// 多页面应用
	entry: {
		pageOne: './src/pageOne/index.js',
		pageTwo: './src/pageTwo/index.js'
	}
	/**
		我们告诉webpack需要三个独立分离的依赖图,
		在多页面应用程序中,服务器会传输一个新的html文档给客户端。
		页面重新加载此新文档,并且资源被重新下载。
	**/
};
  • Output

    output属性告诉webpack在哪里输出它所创建的bundles,以及如何命名这些文件,默认值为./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: 'bundle.js',
    /**
		如果配置创建了多个单独的chunk,则应该使用占位符来确保每个文件具有唯一个名称
		filename: '[name].js'	
	**/
    publicPath: 'http://cdn.example.com/assets/[hash]/'
    /**
		如果在编译时,不知道最终输出文件的publicPath是什么地址,则可以将其留空,
		并且在运行时通过入口起点文件中的_webapck_public_path_动态设置
		__webpack_public_path__ = myRuntimePublicPath;
		// 应用程序入口的其余部分
	**/
  }
};
  • Module

    模块,在webpack里一切皆模块,一个模块对应着一个文件。webpack会从配置的Entry开始递归找出所有依赖的模块

  • Chunk

    代码块,一个Chunk由多个模块组合而成,用于代码合并与分割

  • Loader

    loader让webpack能够去处理那些非JavaScript文件(webpack自身只理解JavaScript和JSON文件)。可以将所有类型的文件转换为webpack能够处理的有效模块,然后你就可以利用webpack的打包能力,对它们进行处理。本质上,webpack loader将所有类型的文件,转换为应用程序的依赖图(和最终的bundle)可以直接引用的模块。
    webpack的配置中loader由两个属性:

    1. test属性,用户标识出应该被对应的loader进行转换的某个或某些文件。
    2. use属性,表示进行转换时,应该使用哪个loader
const path = require('path');

module.exports = {
  output: {
    filename: 'my-first-webpack.bundle.js'
  },
  module: {
    rules: [
      { test: /\.txt$/, use: 'raw-loader' }
    ]
  }
};
  • Plugin

    loader被用于转换某些类型的模块,而插件则可以用于执行范围更广的任务。插件的范围包括,从打包优化和压缩,一直到重新定义环境中的变量。插件接口功能极其强大,可以用来处理各种各样的任务。
    想要使用一个插件,你只需要require()它,然后把它添加到plugins数组中。多数插件可以通过选项(option)自定义,你也可以在一个配置文件中因为不同目的而多次使用同一个插件,这时需要通过使用new操作符来创建它的一个实例。

const HtmlWebpackPlugin = require('html-webpack-plugin'); // 通过 npm 安装
const webpack = require('webpack'); // 用于访问内置插件

module.exports = {
  module: {
    rules: [
      { test: /\.txt$/, use: 'raw-loader' }
    ]
  },
  plugins: [
    new HtmlWebpackPlugin({template: './src/index.html'})
  ]
};
  • 模式

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

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

如何提高webpack的打包速度?

1、分析打包速度
通过 speed-measure-webpack-plugin 测量你的webpack构建期各个阶段花费的事件

// 分析打包时间
const SpeedMeasurePlugin = require("speed-measure-webpack-plugin")
const smp = new SpeedMeasurePlugin()
// ...
module.exports = smp.wrap(prodWebpackConfig)

2、分析bundle包

  • 打包后的bundle文件生成一个分析文件
"analyse": "webpack --config ./webpack.config.js --profile --json>states.json"
  • 进一步分析 chunks 文件
    在绝大多数的情况下,应用刚开始工作时,并不是所有的模块都是必需的。如果这些模块全部被打包到一起,即便应用只需要一两个模块工作,也必须先把 bundle.js 整体加载进来,而且前端应用一般都是运行在浏览器端,这也就意味着应用的响应速度会受到影响,也会浪费大量的流量和带宽。
    开发环境下的 bunlde 依赖表也能看出 node_modules 中大部分内容是随着 app.js 一起打包,这些就是引起我们打包速度缓慢的元凶
    当我们代码有更新时,HMR 会重新打包 app.js,也就是说那些没有被修改的 node_modules 中内容也会跟着重新打包到 app.js 中去

  • 代码分割
    高达 6M 的入口文件显然是非常影响体验的,因此优化的第一步就是从代码分割开始。代码分割通过把项目中的资源模块按照我们设计的规则打包到不同的 bundle 中,从而降低应用的启动成本,提高响应速度。

项目本身已经配置了多入口,将 lodash 等三方库文件单独进行打包,生成 vendor.js 文件
将入口文件依赖的 node_modules 中内容打包到 common 中,将业务代码进行单独打包,这样可以有效减少 app.js 的体积

new webpack.optimize.CommonsChunkPlugin({
  name: 'common',
  minChunks: function(module) {
    return (
      module.resource &&
      /\.js$/.test(module.resource) &&
      module.resource.indexOf(
        path.join(__dirname, './node_modules')
      ) === 0
    )
  }
})

3、速度优化
很显然在开发过程中进行 webpack 缓存是极其有必要的,我们在处理样式文件和 js 文件的 loader 之前添加 cache-loader 将结果缓存到磁盘中,可以显著提升二次构建速度

module.exports = {
  module: {
    rules: [
      {
        test: /\.js$/,
        use: ['cache-loader', ...loaders],
        include: path.resolve('src'),
      },
      {
        test: /\.scss$/,
        use: ['cache-loader', ...loaders],
        include: path.resolve('src'),
      },
    ],
  },
};

官网
配置项

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值