@tgwf/co2 0.6.1 → 0.9.0-0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,26 @@
1
+ name: Unit tests
2
+ on:
3
+ push:
4
+ branches:
5
+ - main
6
+ pull_request:
7
+ branches:
8
+ - main
9
+ jobs:
10
+ build:
11
+ runs-on: ubuntu-latest
12
+ strategy:
13
+ matrix:
14
+ node-version: [12.x, 14.x, 16.x]
15
+ steps:
16
+ - uses: actions/checkout@v2
17
+ - name: Use Node.js ${{ matrix.node-version }}
18
+ uses: actions/setup-node@v1
19
+ with:
20
+ node-version: ${{ matrix.node-version }}
21
+ - name: Install
22
+ run: npm ci
23
+ - name: Verify lint
24
+ run: npm run lint
25
+ - name: Run unit tests
26
+ run: npm test
package/CHANGELOG.md CHANGED
@@ -5,12 +5,52 @@ All notable changes to this project will be documented in this file.
5
5
  The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
6
6
  and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
7
  -
8
+
8
9
  ## Unreleased
9
10
 
10
11
 
11
- - Include the new alternative, "Green Byte Model" with the figures after speaking to folks at the IEA and other places.
12
12
 
13
- ## ## [0.6.1] - 2020-03-15
13
+ # [0.9.0] - 2022-03-28
14
+
15
+ ### Added
16
+
17
+ - Added newly implemented Sustainable Web Design model [thanks @dryden!]
18
+ - Added new readme page for using both emissions models
19
+ - Added new source of data to the Sustainable Web Design model from Ember Climate.
20
+ ### Changed
21
+
22
+ - Changed the CO2 class to accept either the One Byte model or the Sustainable Web Design model
23
+ ### Fixed
24
+
25
+ - Fixed various typos.
26
+
27
+ # [0.8.0] - 2021-11-28
28
+
29
+ ### Fixed
30
+
31
+ - Update further dependencies
32
+ - Fix embarassing order of magnitude typo in 1byte model (thanks @mstaschik!)
33
+
34
+ ## Added
35
+
36
+ - Read JSON blob also as gzipped #44 (thanks @soulgalore)
37
+
38
+ ### Changed
39
+
40
+ - The 1byte model will give different numbers now. It's mentioned in `#fixed` but it's worth repeating.
41
+
42
+ ## [0.7.0] - 2021-11-28
43
+
44
+ ### Fixed
45
+
46
+ - Update tests to avoid network requests #50
47
+ - Update dependencies across the board
48
+
49
+ ### Changed
50
+
51
+ - Switch to github actions instead of travis for CI.
52
+
53
+ ## [0.6.1] - 2020-03-15
14
54
 
15
55
  ### Fixed
16
56
 
@@ -35,9 +75,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
35
75
 
36
76
  ### Changed
37
77
 
38
- - Update README
39
- - Update the emissions figured for green energy after further research on methodology with @@JamieBeevor
40
- - Incorproate class based CO2 models from @soulgalore
78
+ - Updated README
79
+ - Updated the emissions figured for green energy after further research on methodology with @@JamieBeevor
80
+ - Incorporated class based CO2 models from @soulgalore
41
81
  - Credit contributors
42
82
 
43
83
 
@@ -57,7 +97,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
57
97
 
58
98
  ### Added
59
99
 
60
- Add the (currently unused) green byte model.
100
+ Added the (currently unused) green byte model.
61
101
 
62
102
  ### Changed
63
103
 
package/README.md CHANGED
@@ -1,40 +1,77 @@
1
1
  # CO2
2
2
 
3
- <img src="https://travis-ci.org/thegreenwebfoundation/co2.js.svg?branch=master" />
3
+ <img src="https://github.com/thegreenwebfoundation/co2.js/actions/workflows/unittests.yml/badge.svg" />
4
4
 
5
- We know computers use electricity, and because most of the electricity we use comes from burning fossil fuels to generate, there is an environmental cost to every upload and download we make over the internet.
6
5
 
7
- We cando something about this though. The same way we use performance budgets make apps and website faster and cheaper to run, we can use carbon budgets to make them faster, cheaper and _greener_.
6
+ We know computers use electricity, and because most of the electricity we use comes from burning fossil fuels, there is an environmental cost to every upload and download we make over the internet.
7
+
8
+ We can do something about this though. The same way we use performance budgets to make apps and websites faster and cheaper to run, we can use carbon budgets to make them faster, cheaper and _greener_.
8
9
 
9
10
  The CO2 package from [The Green Web Foundation][tgwf] lets you quickly estimate these emissions, to make measurable improvements as part of your workflow.
10
11
 
11
- It does this by implementing the 1byte model as used by the Shift Project, as introduced in their report on CO2 emissions from digital infrastructure, [Lean ICT: for a sober digital][soberDigital], to return a number for the estimated CO2 emissions for the corresponding number of bytes sent over the wire.
12
+ ### How it works
13
+
14
+ It does this by implementing various models for converting the measurable usage of digital services into a figure for the estimated CO2 emissions.
15
+
16
+ This defaults to the 1byte model as used by the Shift Project, as introduced in their report on CO2 emissions from digital infrastructure, [Lean ICT: for a sober digital][soberDigital], with the [Sustainable Web Design model][swd] as a popular alternative..
12
17
 
13
- It is currently used in the web performance tool [sitespeed.io][], to help developers build greener, more planet friendly digital services.
18
+ For more information, see the documentation [for when to use the different models, with code samples to start you off](./src/readme.md).
19
+
20
+ ### Who uses it
21
+
22
+ It is currently used in the web performance tool [sitespeed.io][], [ecoping][], [Websitecarbon.com](websitecarbon), and [ecograder][] to help developers build greener, more planet friendly digital services.
14
23
 
15
24
  If you want to build this kind of environmental information into your own software, and want some advice, we'd be happy to hear from you - please open an issue, remembering to link to your project.
16
25
 
17
- This is open source software, with all the guarantees associated, so if you want professional advice, to a deadline, and you have a budget please see the services offered by the [Green Web Foundation][tgwf-services].
26
+ This is open source software, with all the guarantees associated. So if you want professional advice, to a deadline, and you have a budget please see the services offered by the [Green Web Foundation][tgwf-services].
27
+
18
28
 
29
+ [sitespeed.io]: https://sitespeed.io
30
+ [ecoping]: https://ecoping.earth
31
+ [ecograder]: https://ecograder.com
32
+ [websitecarbon]: https://www.websitecarbon.com
33
+ [tgwf]: https://www.thegreenwebfoundation.org
34
+ [tgwf-services]: https://www.thegreenwebfoundation.org/services
35
+ [swd]: https://sustainablewebdesign.org/calculating-digital-emissions
19
36
  [soberDigital]: https://theshiftproject.org/en/lean-ict-2/
20
- [sitespeed.io]: https://sitespeed.io/
21
- [tgwf]: https://www.thegreenwebfoundation.org/
22
- [tgwf-services]: https://www.thegreenwebfoundation.org/services/
23
37
 
24
38
 
25
39
  ## Usage
26
40
 
41
+ ### Calculating emissions per byte
42
+
43
+ #### Server-side
44
+
45
+ This approach relies on the `fs` module and so can only be used on platforms like Node.js, that support this.
46
+
27
47
  ```js
28
48
 
29
49
  const CO2 = require('@tgwf/co2')
30
- const bytesSent = 1_000_000
50
+ const bytesSent = (1024 * 1024 * 1024)
31
51
  const co2Emission = new CO2();
32
52
  estimatedCO2 = co2Emission.perByte(bytesSent)
33
53
 
34
- console.log(`Sending a million bytes, had a carbon footprint of ${estimatedCO2.toFixed(3)} grams of CO2`)
54
+ console.log(`Sending a gigabyte, had a carbon footprint of ${estimatedCO2.toFixed(3)} grams of CO2`)
55
+
56
+ ```
57
+
58
+ #### Browser-side
35
59
 
60
+ For browser-based solutions, you must import the `co2.js` submodule directly from `node_modules`. For example, like this:
61
+
62
+ ```js
63
+
64
+ const CO2 = require('node_modules/@tgwf/co2/src/co2.js')
65
+ const bytesSent = (1024 * 1024 * 1024)
66
+ const co2Emission = new CO2();
67
+ estimatedCO2 = co2Emission.perByte(bytesSent)
68
+
69
+ console.log(`Sending a gigabyte, had a carbon footprint of ${estimatedCO2.toFixed(3)} grams of CO2`)
70
+ ****
36
71
  ```
37
72
 
73
+ ### Checking for green power
74
+
38
75
  Because different digital services and websites use different forms of power, there is also a module for checking if a domain uses green power or not, and whether the domains linked to on a page use green power as well.
39
76
 
40
77
  ```js
@@ -44,25 +81,14 @@ const greencheck = require('@tgwf/hosting')
44
81
  // returns true if green, otherwise false
45
82
  greencheck.check("google.com")
46
83
 
47
- // returns an array of the green domains, in this case ["google.
48
- greencheck.check(["google.com", "kochindustries.com"]) com"]
84
+ // returns an array of the green domains, in this case ["google.com"].
85
+ greencheck.check(["google.com", "kochindustries.com"])]
49
86
 
50
87
  // returns an array of green domains, again in this case, ["google.com"]
51
88
  greencheck.checkPage(["google.com"])
52
89
 
53
90
  ```
54
91
 
55
- Please note, we currently look at just the carbon cost of _generating_ the electricity, similar to how the IEA does, not the full life cycle cost of the energy, which would include things like:
56
-
57
- - the carbon associated with digging up the fuel
58
- - the carbon associated with mining the materials to build the power stations, datacentres
59
- - the end of life costs
60
- - the maintenance costs over the life of the datacentres, power generation and end user devices, and the rest of the internet
61
-
62
- We'd like to do this, and we know how complicated this is likely to be.
63
-
64
-
65
92
  # Licenses
66
93
 
67
94
  Apache 2.0
68
-
Binary file
@@ -1 +1 @@
1
- ["google.com"]
1
+ ["google.com","maxcdn.bootstrapcdn.com","thegreenwebfoundation.org","www.thegreenwebfoundation.org","fonts.googleapis.com","ajax.googleapis.com","assets.digitalclimatestrike.net","cdnjs.cloudflare.com","graphite.thegreenwebfoundation.org","analytics.thegreenwebfoundation.org","fonts.gstatic.com","api.thegreenwebfoundation.org"]
Binary file
package/package.json CHANGED
@@ -1,10 +1,11 @@
1
1
  {
2
2
  "name": "@tgwf/co2",
3
- "version": "0.6.1",
3
+ "version": "0.9.0-0",
4
4
  "description": "Work out the co2 of your digital services",
5
5
  "main": "src/index.js",
6
6
  "scripts": {
7
7
  "test": "jest",
8
+ "test:watch": "jest --watch",
8
9
  "lint": "eslint .",
9
10
  "lint:fix": "eslint . --fix",
10
11
  "travis": "npm run lint && jest"
@@ -21,15 +22,17 @@
21
22
  "author": "Chris Adams",
22
23
  "license": "Apache-2.0",
23
24
  "devDependencies": {
24
- "@tgwf/url2green": "^0.3.0",
25
- "eslint": "6.8.0",
26
- "eslint-config-prettier": "6.10.0",
27
- "eslint-plugin-jest": "23.8.1",
28
- "eslint-plugin-prettier": "3.1.2",
29
- "jest": "25.1.0",
30
- "np": "^5.2.1",
31
- "pagexray": "^2.5.9",
32
- "prettier": "1.19.1"
25
+ "@tgwf/url2green": "^0.4.0",
26
+ "eslint": "^8.3.0",
27
+ "eslint-config-prettier": "^8.3.0",
28
+ "eslint-plugin-jest": "^25.2.4",
29
+ "eslint-plugin-prettier": "^4.0.0",
30
+ "jest": "^27.3.1",
31
+ "minimist": "^1.2.5",
32
+ "nock": "^13.2.1",
33
+ "np": "^7.6.0",
34
+ "pagexray": "^4.3.1",
35
+ "prettier": "^2.4.1"
33
36
  },
34
37
  "np": {
35
38
  "yarn": false
package/src/1byte.js CHANGED
@@ -1,6 +1,14 @@
1
1
  // Use the 1byte model for now from the Shift Project, and assume a US grid mix figure they use of around 519 g co2 for the time being. It's lower for Europe, and in particular, France, but for v1, we don't include this
2
2
  const CO2_PER_KWH_IN_DC_GREY = 519;
3
3
 
4
+ // this figure is from the IEA's 2018 report for a global average:
5
+ const CO2_PER_KWH_NETWORK_GREY = 475;
6
+
7
+ // TODO - these figures need to be updated, as the figures for green
8
+ // shouldn't really be zero now we know that carbon intensity figures
9
+ // for renewables still usually include the life cycle emissions
10
+ const CO2_PER_KWH_IN_DC_GREEN = 0;
11
+
4
12
  // the 1 byte model gives figures for energy usage for:
5
13
 
6
14
  // datacentres
@@ -9,19 +17,55 @@ const CO2_PER_KWH_IN_DC_GREY = 519;
9
17
 
10
18
  // The device usage figure combines figures for:
11
19
  // 1. the usage for devices (which is small proportion of the energy use)
12
- // 2. the *making* the device, which is comparitively high.
20
+ // 2. the *making* the device, which is comparatively high.
13
21
 
14
- const KWH_PER_BYTE_IN_DC = 0.00000000072;
22
+ const KWH_PER_BYTE_IN_DC = 7.2e-11;
15
23
 
16
24
  // this is probably best left as something users can define, or
17
25
  // a weighted average based on total usage.
26
+ // Using a simple mean for now, as while web traffic to end users might trend
27
+ // towards wifi and mobile,
28
+ // Web traffic between servers is likely wired networks
29
+
30
+ const FIXED_NETWORK_WIRED = 4.29e-10;
31
+ const FIXED_NETWORK_WIFI = 1.52e-10;
32
+ const FOUR_G_MOBILE = 8.84e-10;
33
+
18
34
  // Pull requests gratefully accepted
19
- const KWH_PER_BYTE_FOR_NETWORK = 0.00000000488;
35
+ const KWH_PER_BYTE_FOR_NETWORK =
36
+ (FIXED_NETWORK_WIRED + FIXED_NETWORK_WIFI + FOUR_G_MOBILE) / 3;
37
+
38
+ const KWH_PER_BYTE_FOR_DEVICES = 1.3e-10;
39
+
40
+ class OneByte {
41
+ constructor(options) {
42
+ this.options = options;
43
+
44
+ this.KWH_PER_BYTE_FOR_NETWORK = KWH_PER_BYTE_FOR_NETWORK;
45
+ }
46
+
47
+ perByte(bytes, green) {
48
+ if (bytes < 1) {
49
+ return 0;
50
+ }
51
+
52
+ if (green) {
53
+ // if we have a green datacentre, use the lower figure for renewable energy
54
+ const Co2ForDC = bytes * KWH_PER_BYTE_IN_DC * CO2_PER_KWH_IN_DC_GREEN;
55
+
56
+ // but for the worest of the internet, we can't easily check, so assume
57
+ // grey for now
58
+ const Co2forNetwork =
59
+ bytes * KWH_PER_BYTE_FOR_NETWORK * CO2_PER_KWH_NETWORK_GREY;
60
+
61
+ return Co2ForDC + Co2forNetwork;
62
+ }
63
+
64
+ const KwHPerByte = KWH_PER_BYTE_IN_DC + KWH_PER_BYTE_FOR_NETWORK;
65
+ return bytes * KwHPerByte * CO2_PER_KWH_IN_DC_GREY;
66
+ }
67
+ }
20
68
 
21
- const KWH_PER_BYTE_FOR_DEVICES = 0.00000000013;
22
69
  module.exports = {
23
- KWH_PER_BYTE_IN_DC,
24
- KWH_PER_BYTE_FOR_NETWORK,
25
- KWH_PER_BYTE_FOR_DEVICES,
26
- CO2_PER_KWH_IN_DC_GREY
70
+ OneByte,
27
71
  };
@@ -0,0 +1,17 @@
1
+ "use strict";
2
+
3
+ const oneByte = require("./1byte");
4
+
5
+ describe("onebyte", () => {
6
+ describe("perByte", () => {
7
+ it.only("returns a simple average of the different networks", () => {
8
+ // we limit this to 12 figures with toFixed(12), because
9
+ // we have a recurring 333333 afterwards
10
+ // 4.88e-10 is the same as 0.000000000488
11
+ const expected_val = (0.000000000488).toFixed(12);
12
+ const instance = new oneByte.OneByte();
13
+
14
+ expect(instance.KWH_PER_BYTE_FOR_NETWORK.toFixed(12)).toBe(expected_val);
15
+ });
16
+ });
17
+ });
package/src/co2.js CHANGED
@@ -1,48 +1,33 @@
1
1
  "use strict";
2
2
 
3
3
  const url = require("url");
4
- const oneByte = require("./1byte.js");
5
-
6
- const KWH_PER_BYTE_IN_DC = oneByte.KWH_PER_BYTE_IN_DC;
7
- const KWH_PER_BYTE_FOR_NETWORK = oneByte.KWH_PER_BYTE_FOR_NETWORK;
8
- const CO2_PER_KWH_IN_DC_GREY = oneByte.CO2_PER_KWH_IN_DC_GREY;
9
-
10
- // this figure is from the IEA's 2018 report for a global average:
11
- const CO2_PER_KWH_NETWORK_GREY = 475;
12
-
13
- // The IEA figures cover electricity but as far as I can tell, it does not
14
- // cover life cycle emissions, and the 1byte models appears to do the same
15
- // so, we use zero emissions for green infra in the DC
16
- // https://github.com/thegreenwebfoundation/co2.js/issues/2
17
- const CO2_PER_KWH_IN_DC_GREEN = 0;
4
+ const onebyte = require("./1byte.js");
18
5
 
19
6
  class CO2 {
20
7
  constructor(options) {
21
8
  this.options = options;
22
- }
23
9
 
24
- perByte(bytes, green) {
25
- // return a CO2 figure for energy used to shift the corresponding
26
- // the data transfer.
10
+ // default model
11
+ this.model = new onebyte.OneByte();
27
12
 
28
- if (bytes < 1) {
29
- return 0;
30
- }
31
-
32
- if (green) {
33
- // if we have a green datacentre, use the lower figure for renewable energy
34
- const Co2ForDC = bytes * KWH_PER_BYTE_IN_DC * CO2_PER_KWH_IN_DC_GREEN;
35
-
36
- // but for the rest of the internet, we can't easily check, so assume
37
- // grey for now
38
- const Co2forNetwork =
39
- bytes * KWH_PER_BYTE_FOR_NETWORK * CO2_PER_KWH_NETWORK_GREY;
40
-
41
- return Co2ForDC + Co2forNetwork;
13
+ if (options) {
14
+ this.model = new options.model();
42
15
  }
16
+ }
43
17
 
44
- const KwHPerByte = KWH_PER_BYTE_IN_DC + KWH_PER_BYTE_FOR_NETWORK;
45
- return bytes * KwHPerByte * CO2_PER_KWH_IN_DC_GREY;
18
+ //
19
+ //
20
+ /**
21
+ * Accept a figure in bytes for data transfer, and a boolean for whether
22
+ * the domain shows as 'green', and return a CO2 figure for energy used to shift the corresponding
23
+ * the data transfer.
24
+ *
25
+ * @param {number} bytes
26
+ * @param {boolean} green
27
+ * @return {number} the amount of CO2 in grammes
28
+ */
29
+ perByte(bytes, green) {
30
+ return this.model.perByte(bytes, green);
46
31
  }
47
32
 
48
33
  perDomain(pageXray, greenDomains) {
@@ -57,10 +42,10 @@ class CO2 {
57
42
  co2PerDomain.push({
58
43
  domain,
59
44
  co2,
60
- transferSize: pageXray.domains[domain].transferSize
45
+ transferSize: pageXray.domains[domain].transferSize,
61
46
  });
62
47
  }
63
- co2PerDomain.sort(function(a, b) {
48
+ co2PerDomain.sort(function (a, b) {
64
49
  return b.co2 - a.co2;
65
50
  });
66
51
 
@@ -105,10 +90,10 @@ class CO2 {
105
90
  all.push({
106
91
  type,
107
92
  co2: co2PerContentType[type].co2,
108
- transferSize: co2PerContentType[type].transferSize
93
+ transferSize: co2PerContentType[type].transferSize,
109
94
  });
110
95
  }
111
- all.sort(function(a, b) {
96
+ all.sort(function (a, b) {
112
97
  return b.co2 - a.co2;
113
98
  });
114
99
  return all;
@@ -125,7 +110,7 @@ class CO2 {
125
110
  );
126
111
  allAssets.push({ url: asset.url, co2: co2ForTransfer, transferSize });
127
112
  }
128
- allAssets.sort(function(a, b) {
113
+ allAssets.sort(function (a, b) {
129
114
  return b.co2 - a.co2;
130
115
  });
131
116