源码网商城,靠谱的源码在线交易网站 我的订单 购物车 帮助

源码网商城

浅析webpack 如何优雅的使用tree-shaking(摇树优化)

  • 时间:2021-12-23 10:38 编辑: 来源: 阅读:
  • 扫一扫,手机访问
摘要:浅析webpack 如何优雅的使用tree-shaking(摇树优化)
[b]1.什么是tree-shaking[/b] webpack 2 的到来带来的最棒的新特性之一就是tree-shaking 。tree-shaking源自于rollup.js,先如今,webpack 2也有类似的做法。 webpack 里的tree-shaking的到来不得不归功于es6规范的模块。为什么这么说,如今的前端模块规范很多,比较出流行的比如commonJS , AMD , es6 ,我简单的说一下commonJS和es6模块的区别。 [b]commonJS 模块[/b] commonJS的模块规范在Node中发扬光大,总的来说,它的特性有这几个: [b]1.动态加载模块 [/b] commonJS和es6的最大区别大概就在于此了吧,commonJS模块的动态加载能够很轻松的实现懒加载,优化用户体验。 [b]2.加载整个模块 [/b] commonJS模块中,导出的是整个模块。 [b]3.每个模块皆为对象 [/b] commonJS模块都被视作一个对象。 [b]4.值拷贝 [/b] commonJS的模块输出和 函数的值传递相似,都是值的拷贝 [b]es6 模块[/b] [b]1.静态解析 [/b] 即在解析阶段就确定输出的模块,所以es6模块的import一般写在被引入文件的开头。 [b]2.模块不是对象 [/b] 在es6里,每个模块并不会当做一个对象看待 [b]3.加载的不是整个模块 [/b] 在es6模块中经常会看见一个模块中有好几个export 导出 [b]4.模块的引用 [/b] es6模块中,导出的并不是模块的值拷贝,而是这个模块的引用 在结合es6模块和commonJS模块的区别之后,我们知道es6的特点是静态解析,而commonJS模块的特点是动态解析的,因此,借于es6模块的静态解析,tree-shaking的实现才能成为可能。 在webpack中,tree-shaking指的就是按需加载,即没有被引用的模块不会被打包进来,减少我们的包大小,缩小应用的加载时间,呈现给用户更佳的体验。 [b]2.怎么使用tree-shaking[/b] 说了这么多那到底如何使用tree-shaking呢? webpack默认es6规范编写的模块都能使用tree-shaking。这是什么意思呢?下面来看个例子。 首先奉上我的demo目录如下: ├─dist     └─index.html ├─node_modules     └─... ├─src     ├─scripts     ├─assets ├─webpack.config.js └─package.json dist用来存放打包好的代码 src相反的用来存放源文件 src里的scripts目录用来存放js脚本文件,assets用来存放静态资源文件 以下几条命令过后开始我们的tree-shaking之旅
npm install --save-dev webpack webpack-dev-server
webpack.config.js
const webpack = require('webpack')
const path = require('path')
module.exports = {
  entry:'./src/scripts/main.js',
  output:{
    path:path.resolve(__dirname,'dist/'),
    filename:'main.bundle.js'
  },
  plugins:[
    new webpack.HotModuleReplacementPlugin()
  ],
  devServer:{
    port:4200,
    contentBase:path.resolve(__dirname,'dist/'),
    historyApiFallback:true,
    hot:true
  }
}

接下来是main.js,直接引入了sayHello [code]import { sayHello } from './greeter.ts';[/code] [code]sayHello();[/code] 相应的main.js的依赖greeter.js
export function sayHello(){
  alert('hello')
}
export function sayWorld(){
  alert('world')
}
在dist目录下有个index.html 用来引入打包后的bundle
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>Document</title>
</head>
<body>
  <script type="text/javascript" src="./main.bundle.js"></script>
</body>
</html>
以上就是整个demo的代码,接下来的事情我们直接webpack打包试试看 去掉打包后冗长的代码只看chunk传参的部分: [ /* 0 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; Object.defineProperty(__webpack_exports__, "__esModule", { value: true }); /* harmony import */ var __WEBPACK_IMPORTED_MODULE_0__person__ = __webpack_require__(1); Object(__WEBPACK_IMPORTED_MODULE_0__person__["a" /* sayHello */])(); /***/ }), /* 1 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "a", function() { return sayHello; }); /* unused harmony export sayWorld */     function sayHello(){         alert('hello');     }     function sayWorld(){         alert('world');     } /***/ }) /******/ ] 我们关注这一行
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "a", function() { return sayHello; });
实际上只return了一个sayHello。 因此我们现在只需要压缩一下整个Js代码,就能把没引用的sayWorld剔除。 键入以下命令进行压缩 [code]webpack --optimize-minimize[/code] 由于压缩后的代码只有一行了,我们移步尾部:
function(e,n,r){"use strict";function t(){alert("hello")}r.d(n,"a",function(){return t})}]);
可以看到sayWorld函数已经被成功剔除。 我们启动webpack-dev-server [code]webpack-dev-server[/code] 在浏览器中输入 [url=http://localhost:4200/]http://localhost:4200[/url] [img]http://files.jb51.net/file_images/article/201708/201708161037011.png[/img] 每次都需要在命令行里输入参数,岂不是很麻烦,还有没有其他更好的办法呢? [b](1)[/b]我们可以把这串命令放入package.json的scripts字段,然后通过npm start来自动执行 [b](2)[/b]其实–optimize-minimize的底层实现是一个插件UglifyJsPlugin,因此,我们可以直接在webpack.config.js里配置它 在webpack.config.js里配置插件
const path = require('path');
const webpack = require('webpack');

module.exports = {
  entry:'./src/scripts/main.js',
  output:{
    filename:'main.bundle.js',
    path:path.join(__dirname,'dist')
  },
  plugins:[
    new webpack.optimize.UglifyJsPlugin(), // <----------- 压缩js
    new webpack.HotModuleReplacementPlugin()
  ],
  devServer:{
    port:4200,
    historyApiFallback:true,
    hot:true,
    contentBase:path.join(__dirname,"dist/")
  }
}

然后我们webpack打包 即看到同样的效果
function(e,n,r){"use strict";function t(){alert("hello")}r.d(n,"a",function(){return t})}]);
在tree-shaking触发打包后,仅仅是撇开了模块的引用,但还是要结合压缩工具来进行,这才是完整的一次tree-shaking 那如果是typescript该怎么使用tree-shaking呢? [b]3.如何在typescript里使用tree-shaking[/b] 要在webpack里使用ts,首先我们必须安装tsc [code]npm install --save-dev typescript[/code] 之后我们需要解析ts文件的loader [code]npm install --save-dev ts-loader[/code] 然后在webpack.config.js进行配置
const webpack = require('webpack')
const path = require('path')
module.exports = {
  entry:'./src/scripts/main.ts',
  output:{
    path:path.resolve(__dirname,'dist/'),
    filename:'main.bundle.js'
  },
  module:{
    rules:[
      {
        test:/\.ts$/,
        use:['ts-loader']
      }
    ]
  },
  plugins:[
    new webpack.optimize.UglifyJsPlugin(),
    new webpack.HotModuleReplacementPlugin()
  ],
  devServer:{
    port:4200,
    contentBase:path.resolve(__dirname,'dist/'),
    historyApiFallback:true,
    hot:true
  }
}

献上我的两份文件main.ts , greeter.ts (这两份文件除了后缀名基本没有改动) [b]main.ts[/b]
import { sayHello } from './greeter.ts';

sayHello();
[b]greeter.ts[/b]
export var sayHello = function(){
  alert('hello')
}

export var sayWorld = function(){
  alert('world')
}
之后我们需要做的是,创建一个tsconfig.json的配置文件供tsc解析,这时,坑来了。 下面是我的tsconfig.json文件
{
  "compilerOptions":{
    "target":"es5",
    "sourceMap":true
  },
  "exclude":[
    "./node_modules"
  ]
}
好像没有什么不对 接着我们webpack 看下打包压缩后的代码的最后一部分:
"use strict";Object.defineProperty(n,"__esModule",{value:!0}),n.sayHello=function(){alert("hello")},n.sayWorld=function(){alert("world")}}]);
sayWorld居然还是存在!!!怎么回事,为什么没有被触发tree-shaking优化? 这是因为tsc编译后的代码为es5 ,而正因如此,tsc默认使用了commonJS的规范来加载模块,因此并没有触发tree-shaking,那我们要怎么做? 修改一下tsconfig.json,把target改为es6即可!
{
  "compilerOptions":{
    "target":"es6",
    "sourceMap":true
  },
  "exclude":[
    "./node_modules"
  ]
}
再次打包 看一下打包后的bundle
function(e,n,r){"use strict";r.d(n,"a",function(){return t});var t=function({alert("hello")}}]);
果然是触发了tree-shaking 开启webpack-dev-server [code]webpack-dev-server[/code] 可以看到成功打印hello [img]http://files.jb51.net/file_images/article/201708/201708161037012.png[/img] 以上就是我对webpack tree-shaking的总结,希望对大家的学习有所帮助
  • 全部评论(0)
联系客服
客服电话:
400-000-3129
微信版

扫一扫进微信版
返回顶部