本文共 5566 字,大约阅读时间需要 18 分钟。
if (process.env.NODE_ENV === 'production') { console.log('你正在线上环境');} else { console.log('你正在使用开发环境');}
压缩的方法除了可以通过 GZIP 算法对文件压缩外,还可以对文本本身进行压缩。
对文本本身进行压缩的作用除了有提升网页加载速度的优势外,还具有混淆源码的作用。由于压缩后的代码可读性非常差,就算别人下载到了网页的代码,也大大增加了代码分析和改造的难度。
要在 Webpack 中接入 UglifyJS 需要通过插件的形式,目前有两个成熟的插件,分别是:
在不影响代码正确执行的前提下,最优化的代码压
缩配置为如下:const UglifyJSPlugin = require('webpack/lib/optimize/UglifyJsPlugin');module.exports = { plugins: [ // 压缩输出的 JS 代码 new UglifyJSPlugin({ compress: { // 在UglifyJs删除没有用到的代码时不输出警告 warnings: false, // 删除所有的 `console` 语句,可以兼容ie浏览器 drop_console: true, // 内嵌定义了但是只用到一次的变量 collapse_vars: true, // 提取出出现多次但是没有定义成变量去引用的静态值 reduce_vars: true, }, output: { // 最紧凑的输出 beautify: false, // 删除所有的注释 comments: false, } }), ],};
CDN 又叫内容分发网络,通过把资源部署到世界各地,用户在访问时按照就近原则从离用户最近的服务器获取资源,从而加速资源的获取速度。
const path = require('path');const ExtractTextPlugin = require('extract-text-webpack-plugin');const { WebPlugin} = require('web-webpack-plugin');module.exports = { // 省略 entry 配置... output: { // 给输出的 JavaScript 文件名称加上 Hash 值 filename: '[name]_[chunkhash:8].js', path: path.resolve(__dirname, './dist'), // 指定存放 JavaScript 文件的 CDN 目录 URL publicPath: '//js.cdn.com/id/', }, module: { rules: [ { // 增加对 CSS 文件的支持 test: /\.css$/, // 提取出 Chunk 中的 CSS 代码到单独的文件中 use: ExtractTextPlugin.extract({ // 压缩 CSS 代码 use: ['css-loader?minimize'], // 指定存放 CSS 中导入的资源(例如图片)的 CDN 目录 URL publicPath: '//img.cdn.com/id/' }), }, { // 增加对 PNG 文件的支持 test: /\.png$/, // 给输出的 PNG 文件名称加上 Hash 值 use: ['file-loader?name=[name]_[hash:8].[ext]'], }, // 省略其它 Loader 配置... ] }, plugins: [ // 使用 WebPlugin 自动生成 HTML new WebPlugin({ // HTML 模版文件所在的文件路径 template: './template.html', // 输出的 HTML 的文件名称 filename: 'index.html', // 指定存放 CSS 文件的 CDN 目录 URL stylePublicPath: '//css.cdn.com/id/', }), new ExtractTextPlugin({ // 给输出的 CSS 文件名称加上 Hash 值 filename: `[name]_[contenthash:8].css`, }), // 省略代码压缩插件配置... ],};
Tree Shaking 可以用来剔除 JavaScript 中用不上的死代码。
需要注意的是,要让 Tree Shaking 正常工作的前提是交给 Webpack 的 JavaScript 代码必须是采用 ES6 模块化语法的。还得经过 UglifyJS 配合去处理一遍目前的 Tree Shaking 还有些的局限性,经实验发现:
- 不会对entry入口文件做 Tree Shaking。
- 不会对异步分割出去的代码做 Tree Shaking。
大部分 Npm 中的代码都是采用的 CommonJS 语法, 这导致 Tree Shaking 无法正常工作而降级处理。
但是有些库在发布到 Npm 上时会同时提供两份代码,一份采用 CommonJS 模块化语法,一份采用 ES6 模块化语法。 并且在 package.json 文件中分别指出这两份代码的入口。以 redux 库为例:
// package.json{ "main": "lib/index.js", // 指明采用 CommonJS 模块化的代码入口 "jsnext:main": "es/index.js" // 指明采用 ES6 模块化的代码入口}
module.exports = { resolve: { // 针对 Npm 中的第三方模块优先采用 jsnext:main 中指向的 ES6 模块化语法的文件 mainFields: ['jsnext:main', 'browser', 'main'] },};
公共部分的代码提取出来放到 common.js
,
base.js
。 只要不升级基础库的版本,base.js 的文件内容就不会变化,缓存就不会被更新。 由于 base.js 通常会很大,这对提升网页加速速度能起到很大的效果。
在给单页应用做按需加载优化时,一般采用以下原则:
也就是当用户操作到了或者即将操作到对应的功能时再去加载对应的代码。
例:
getAsyncComponent
函数配合 ReactRouter
去按需加载组件:
import React, { PureComponent, createElement} from 'react';import { render} from 'react-dom';import { HashRouter, Route, Link} from 'react-router-dom';import PageHome from './pages/home';/** * 异步加载组件 * @param load 组件加载函数,load 函数会返回一个 Promise,在文件加载完成时 resolve * @returns {AsyncComponent} 返回一个高阶组件用于封装需要异步加载的组件 */function getAsyncComponent(load) { return class AsyncComponent extends PureComponent { componentDidMount() { // 在高阶组件 DidMount 时才去执行网络加载步骤 load().then(({ default: component}) => { // 代码加载成功,获取到了代码导出的值,调用 setState 通知高阶组件重新渲染子组件 this.setState({ component, }) }); } render() { const { component} = this.state || { }; // component 是 React.Component 类型,需要通过 React.createElement 生产一个组件实例 return component ? createElement(component) : null; } }}// 根组件function App() { return ()}// 渲染根组件render(
import(/* webpackChunkName: 'page-about' */'./pages/about') )} /> import(/* webpackChunkName: 'page-login' */'./pages/login') )} /> , window.document.getElementById('app'));
配置相关:
安装一个 Babel 插件 babel-plugin-syntax-dynamic-import,并且将其加入到 .babelrc 中去:
{ "presets": [ "env", "react" ], "plugins": [ "syntax-dynamic-import" ]}
输出在 /* webpackChunkName: “show” */ 中配置的 ChunkName:
module.exports = { // JS 执行入口文件 entry: { main: './main.js', }, output: { // 为从 entry 中配置生成的 Chunk 配置输出文件的名称 filename: '[name].js', // 为动态加载的 Chunk 配置输出文件的名称 chunkFilename: '[name].js', }};
/* webpackChunkName: “show” / 的含义是为动态生成的 Chunk 赋予一个名称,以方便我们追踪和调试代码。 如果不指定动态生成的 Chunk 的名称,默认名称将会是 [id].js。 / webpackChunkName: “show” */ 是在 Webpack3 中引入的新特性,在 Webpack3 之前是无法为动态生成的 Chunk 赋予名称的。
转载地址:http://szrgn.baihongyu.com/