资讯专栏INFORMATION COLUMN

Webpack 最佳实践总结(一)

jubincn / 1690人阅读

摘要:它会代替所有的实例的值为,从而使知道那些判断表达式总是错误的,从而删除相关代码,进一步压缩打包文件模块机制项目中使用的,通过也能通过打包有用的代码,进一步减少大小。

好久没写文章,这次预计会带来3篇的 Webpack 系列文章,将会在这几天内更新完。

Webpack3 自今年6月20日正式发布而来,给我们带来Scope HoistingMagic Comments两大功能,可惜不在这次系列文章内容范畴里,而本次文章的主要内容是从项目中总结得到,当然也看了很多别人写的文章,是可以被应用到生产中。这次主要介绍三个方面,分别是压缩 JavaScript 和 CSS、配置环境变量、ES 模块机制带来的Tree-shaking。

假设我们有一个前端开发需求,这个需求有点特别,不是业务上的需求,而是要求减少文件的大小。可知这个需求算是性能优化上范畴,减少文件大小,加速网络传输,缩短网页加载时间,增加用户体验,提高用户满意度。这是一个正向结果,得干~

压缩 JavaScript

这里不得不提一下 Google 的 Closure Compiler,一款可以让 JavaScript 下载与执行更快的工具,它的做法是执行一些"焦土"(scorched-earth)优化策略,它将函数展开,重写变量名,过滤多余代码,删除从不会调用的函数,从而生成可能是最优化的代码。如下

优化前

function map(array, iteratee) {
  let index = -1
  const length = array == null ? 0 : array.length
  const result = new Array(length)

  while (++index < length) {
    result[index] = iteratee(array[index], index, array)
  }
  return result
}

优化后

function map(n,e){let r=-1;for(const i=null==n?0:n.length,t=Array(i);++r

对比发现优化效果极好,如果使用 UglifyJS 一样可以达到相同的优化效果。由于 Webpack 内置这款插件,可以直接使用,配置如下

// webpack.config.js
const webpack = require("webpack");

module.exports = {
  plugins: [
    new webpack.optimize.UglifyJsPlugin()
  ]
};

使用该插件优化前后的对比结果如下说明:

假设我们有一段代码,如下:

// comments.js
import "./comments.css";
export function render(data, target) {
    console.log("Rendered!");
}

Webpack 编译之后的代码大概如下:

// bundle.js (part of)
"use strict";
Object.defineProperty(__webpack_exports__, "__esModule", { value: true });
var __WEBPACK_IMPORTED_MODULE_0__comments_css__ =
  __webpack_require__(4);
var __WEBPACK_IMPORTED_MODULE_0__comments_css___default =
  __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_0__comments_css__);
__webpack_exports__["render"] = render;

function render(data, target) {
    console.log("Rendered!");
}

如果使用了 UglifyJS 插件,重新编译之后的代码大概如下:

// bundle.js (part of)
"use strict";function r(e,t){console.log("Rendered!")}
Object.defineProperty(t,"__esModule",{value:!0});
var o=n(4);n.n(o);t.render=r

特殊情况说明:目前,UglifyJS 2(Webpack自带的) 是无法编译 ES2015+ 的代码,意味着如果代码中是了类、箭头函数或者其他新的特性,而且你没有将代码编译为 ES5,那么 UglifyJS 插件是无法处理这些代码的,这里提供两种处理方法:

方法1:给 Webpack 添加支持 babel,基本过程如下

安装 babel-corebabel-loaderbabel-preset-es2015

npm i babel-core babel-loader babel-preset-es2015 --save-dev

给 Webpack 添加配置信息

// webpack.config.js
module.exports = {
  module: {
    rules: [
      {
        test: /.js[x]$/,
        use: [{"babel-loader", options: {
          presets: ["es2015"]
        }]
      }
    ]
  }
};

方法2:使用 Babili 取代 UglifyJS 2,这是一款基于 Babel 的压缩工具,更多了解查看 babili-webpack-plugin,这里不作太多的描述

压缩 CSS

压缩 CSS 的方法比较简单,css-loader 就自带压缩功能,配置如下:

// webpack.config.js
module.exports = {
  module: {
    rules: [
      {
        test: /.css$/,
        use: [
          "style-loader",
          { loader: "css-loader", options: { minimize: true } }
        ]
      }
    ]
  }
};

另外我还写过 Webpack 跟 Less 和 Sass 的配置教程,具体看:here1, here2

配置环境变量

NODE_ENV设置为production也能帮助减少前端项目大小

NODE_ENV通常作为环境变量被各种js框架或库作为判断条件去作为哪种执行模式,如开发模式或是生产模式,这些框架或者库根据NODE_ENV的值去表现对应的行为。例如,当处于开发模式时,React 会做额外的检测和打印警告:

// …
if (process.env.NODE_ENV !== "production") {
  validateTypeDef(Constructor, propTypes, "prop");
}
// …

如果要打包构建项目到生产环境中,最好可以告诉项目中的框架或库当前的环境变量是生产环境。对于适用于 Node.js 的库来说,直接配置NODE_ENVproduction即可,但对于 Web 端来说,可以使用 Webpack 自带的插件实现对
process.env.NODE_ENV的设置,如下

// webpack.config.js
const webpack = require("webpack");

module.exports = {
  plugins: {
    new webpack.DefinePlugin({
      "process.env.NODE_ENV": ""production""
    })
  }
};

DefinePlugin 允许我们创建全局变量,同时这些变量会作用于webpack的打包编译期内。它会代替所有的process.env.NODE_ENV实例的值为"production",从而使 UglifyJS 知道那些判断表达式总是错误的,从而删除相关代码,进一步压缩打包文件

ECMAScript模块机制

项目中使用 ECMAScript 的importexport,Webpack 通过 tree-shaking 也能通过打包有用的代码,进一步减少大小。 Tree-shaking 可以检查整个打包依赖树,找到使用的部分。所以如果使用 ECMAScript 模块机制,Webpack 会去掉无用的代码,如下:

假设写了两个文件,但只使用了其中一个文件

// comments.js
export const commentRestEndpoint = "/rest/comments";
export const render = () => { return "Rendered!"; };

// index.js
import { render } from "./a.js";
render();

Webpack 知道componentRestEndpoint是没有被使用,打包文件也不会有该入口

// bundle.js (part of)
(function(module, __webpack_exports__, __webpack_require__) {
  "use strict";
  /* unused harmony export commentRestEndpoint */
  /* harmony export */__webpack_exports__["b"] = render;

  var commentRestEndpoint = "/rest/comments";
  var render = function () { return "Rendered!"; }
})

UglifyJS 插件去掉无用部分

// bundle.js (part of)
(function(n,e){"use strict";e.b=r;var r=function(){return"Rendered!"}})

如果 JavaScript 框架或库使用了 ECMAScript 模块机制,那么 Tree-shaking 是对其也是有效滴

注意事项

1、 如果没有 UglifyJS ,tree-shaking 将不作用

实际上,去掉无用的代码不是 Webpack 本身,而是 UglifyJS。Webpack 只是去掉 export 表达式使那些 exports 不再使用,从而可以在压缩的时候被去掉。因此,如果你打包的时候没有使用压缩,打包文件就不会变得更小

2、不要将 ES 模块机制编译为 CommonJS

如果你使用了 babel-preset-envbabel-preset-es2015,就需要检查一下这些 preset 的配置了。默认情况下,它们都会ES 模块机制的语法特性重新编译为 CommonJS,如将 ES 的importexport编译为 CommonJS 的requiremodule.exports。我们可以使用 { modules: false } 禁止编译行为,如下:

// webpack.config.js
module.exports = {
  module: {
    rules: [
      {
        test: /.js[x]$/,
        use: [{"babel-loader", options: {
          presets: [["es2015", { modules: false }]]
        }]
      }
    ]
  }
};

3、在特殊条件下 Webpack 不会进行优化

当你使用了export * from "file.js" 或者是 TypeScript,Webpack 是不会进行优化。这些特殊条件在代码中很难被发觉,也很难知道这些特殊条件的代码是否被修复,更多了解可以查看 here

总结

Webpack 对前端项目优化有很多种,这里提供了四种技巧,分别是通过 UglifyJS 插件实现对 JavaScript 文件的压缩,css-loader 提供的压缩功能,配置NODE_ENV可以进一步去掉无用代码,tree-shaking帮助找到更多无用代码

内容较多,大概就这样~

文章首发于:https://www.linpx.com/p/webpa...
欢迎访问我的博客:https://www.linpx.com

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/87338.html

相关文章

  • Webpack 最佳实践总结(三)

    摘要:这里要介绍的是工作流中的一种很普遍的代码加工流程正常的业务逻辑开发流程需要经过预处理器如或,然后再经过后处理器如进行深加工。 还未看的,可以点击查看上两篇文章哟:Webpack 最佳实践总结(一)、Webpack 最佳实践总结(二) 好了,这篇是第三篇,也是完结篇,我感觉这一篇是最乱的一篇,凑合着看吧,不会让你失望的 整合 CSS 加工流 有时候,前端项目中除了 JavaScript ...

    pkhope 评论0 收藏0
  • Webpack 最佳实践总结(三)

    摘要:这里要介绍的是工作流中的一种很普遍的代码加工流程正常的业务逻辑开发流程需要经过预处理器如或,然后再经过后处理器如进行深加工。 还未看的,可以点击查看上两篇文章哟:Webpack 最佳实践总结(一)、Webpack 最佳实践总结(二) 好了,这篇是第三篇,也是完结篇,我感觉这一篇是最乱的一篇,凑合着看吧,不会让你失望的 整合 CSS 加工流 有时候,前端项目中除了 JavaScript ...

    jerryloveemily 评论0 收藏0
  • Webpack 最佳实践总结(二)

    摘要:默认做法是告诉浏览器这个文件的缓存时间,然后当文件内容被修改,则需要重命名该文件告诉浏览器需要重新下载和缓存,例如也能做类似的工作。 上一篇介绍了 Webpack 优化项目的四种技巧,分别是通过 UglifyJS 插件实现对 JavaScript 文件的压缩,css-loader 提供的压缩功能,配置NODE_ENV可以进一步去掉无用代码,tree-shaking帮助找到更多无用代码 ...

    Stardustsky 评论0 收藏0
  • webpack-best-practice-最佳实践-部署生产

    摘要:如果是在生产环境下,则加入插件,执行代码压缩,并且去除。规定了在开发环境下才使用。疑问目前为止,对于多页面项目还是没有找到一个很好的方案去构建自动化。原文可以看我的博客最佳实践部署生产 tip webpack的入门篇可以看我的这一片博文。《如何使用webpack—webpack-howto》. 前言 最近一段时间在项目中使用了webpack和React来开发,总之来说也是遇到了许多坑,...

    txgcwm 评论0 收藏0
  • Vue开发总结最佳实践 (已更新)

    摘要:基本开发环境创建的项目,作为代码编写工具插件推荐插件配置文章目录项目目录结构介绍框架选择处理请求二次封装项目目录结构简介业务相关静态文件全局组件基础样式布局样式及工具引入请求配置路由全局状态管理工具文件入口文件主要配置文件页面检查配置测试 基本开发环境 vue-cli3 创建的项目,vscode 作为代码编写工具vscode插件推荐:vscode 插件配置 文章目录 项目目录结构介绍...

    NotFound 评论0 收藏0

发表评论

0条评论

jubincn

|高级讲师

TA的文章

阅读更多
最新活动
阅读需要支付1元查看
<