Reduce script size (#68)

* Remove cookie code

* Compile tracker separetly from website assets

* Install uglify

* Help minifier reduce varaibles
This commit is contained in:
Uku Taht 2020-05-29 09:51:16 +03:00 committed by GitHub
parent 01bc5911d1
commit 4bd12f03fc
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
11 changed files with 259 additions and 246 deletions

1
.gitignore vendored
View File

@ -27,6 +27,7 @@ npm-debug.log
# The directory NPM downloads your dependencies sources to. # The directory NPM downloads your dependencies sources to.
/assets/node_modules/ /assets/node_modules/
/tracker/node_modules/
# Since we are building assets from assets/, # Since we are building assets from assets/,
# we ignore priv/static. You may want to comment # we ignore priv/static. You may want to comment

View File

@ -39,6 +39,7 @@ RUN set -x \
COPY config ./config COPY config ./config
COPY assets ./assets COPY assets ./assets
COPY tracker ./tracker
COPY priv ./priv COPY priv ./priv
COPY lib ./lib COPY lib ./lib
COPY mix.exs ./ COPY mix.exs ./
@ -51,6 +52,8 @@ RUN mix local.hex --force && \
RUN npm audit fix --prefix ./assets && \ RUN npm audit fix --prefix ./assets && \
npm install --prefix ./assets && \ npm install --prefix ./assets && \
npm run deploy --prefix ./assets && \ npm run deploy --prefix ./assets && \
npm install --prefix ./tracker && \
npm run deploy --prefix ./tracker && \
mix phx.digest priv/static mix phx.digest priv/static
WORKDIR /app WORKDIR /app

View File

@ -1,127 +0,0 @@
(function(window, plausibleHost){
'use strict';
try {
const CONFIG = {
domain: window.location.hostname
}
function setCookie(name,value) {
var date = new Date();
date.setTime(date.getTime() + (3*365*24*60*60*1000)); // 3 YEARS
var expires = "; expires=" + date.toUTCString();
document.cookie = name + "=" + (value || "") + expires + "; samesite=strict; path=/";
}
function getCookie(name) {
let matches = document.cookie.match(new RegExp(
"(?:^|; )" + name.replace(/([\.$?*|{}\(\)\[\]\\\/\+^])/g, '\\$1') + "=([^;]*)"
));
return matches ? decodeURIComponent(matches[1]) : null;
}
function ignore(reason) {
console.warn('[Plausible] Ignoring event because ' + reason);
}
function getUrl() {
return window.location.protocol + '//' + window.location.hostname + window.location.pathname + window.location.search;
}
function getSourceFromQueryParam() {
const result = window.location.search.match(/[?&](ref|source|utm_source)=([^?&]+)/);
return result ? result[2] : null
}
function getUserData() {
var userData = JSON.parse(getCookie('plausible_user'))
if (userData) {
return {
initial_referrer: userData.initial_referrer && decodeURIComponent(userData.initial_referrer),
initial_source: userData.initial_source && decodeURIComponent(userData.initial_source)
}
} else {
userData = {
initial_referrer: window.document.referrer || null,
initial_source: getSourceFromQueryParam(),
}
setCookie('plausible_user', JSON.stringify({
initial_referrer: userData.initial_referrer && encodeURIComponent(userData.initial_referrer),
initial_source: userData.initial_source && encodeURIComponent(userData.initial_source),
}))
return userData
}
}
function trigger(eventName, options) {
if (/^localhost$|^127(?:\.[0-9]+){0,2}\.[0-9]+$|^(?:0*\:)*?:?0*1$/.test(window.location.hostname)) return ignore('website is running locally');
if (window.location.protocol === 'file:') return ignore('website is running locally');
if (window.document.visibilityState === 'prerender') return ignore('document is prerendering');
var payload = CONFIG['trackAcquisition'] ? getUserData() : {}
payload.name = eventName
payload.url = getUrl()
payload.domain = CONFIG['domain']
payload.referrer = window.document.referrer || null
payload.source = getSourceFromQueryParam()
payload.user_agent = window.navigator.userAgent
payload.screen_width = window.innerWidth
var request = new XMLHttpRequest();
request.open('POST', plausibleHost + '/api/event', true);
request.setRequestHeader('Content-Type', 'text/plain');
request.send(JSON.stringify(payload));
request.onreadystatechange = function() {
if (request.readyState == XMLHttpRequest.DONE) {
options && options.callback && options.callback()
}
}
}
function page(options) {
trigger('pageview', options)
}
function trackPushState() {
var his = window.history
if (his.pushState) {
var originalFn = his['pushState']
his.pushState = function() {
originalFn.apply(this, arguments)
page();
}
}
window.addEventListener('popstate', page)
}
function configure(key, val) {
CONFIG[key] = val
}
const functions = {
page: page,
trigger: trigger,
trackPushState: trackPushState,
configure: configure
}
const queue = window.plausible.q || []
window.plausible = function() {
var args = [].slice.call(arguments);
var funcName = args.shift();
functions[funcName].apply(this, args);
};
for (var i = 0; i < queue.length; i++) {
window.plausible.apply(this, queue[i])
}
} catch (e) {
new Image().src = plausibleHost + '/api/error?message=' + encodeURIComponent(e.message);
}
})(window, BASE_URL);

View File

@ -1,115 +0,0 @@
(function(window, plausibleHost){
'use strict';
try {
const scriptEl = window.document.querySelector('[src*="' + plausibleHost +'"]')
const domainAttr = scriptEl && scriptEl.getAttribute('data-domain')
const trackAcquisitionAttr = scriptEl && scriptEl.getAttribute('data-track-acquisition')
const CONFIG = {
domain: domainAttr || window.location.hostname,
trackAcquisition: typeof(trackAcquisitionAttr) === 'string'
}
function setCookie(name,value) {
var date = new Date();
date.setTime(date.getTime() + (3*365*24*60*60*1000)); // 3 YEARS
var expires = "; expires=" + date.toUTCString();
document.cookie = name + "=" + (value || "") + expires + "; samesite=strict; path=/";
}
function getCookie(name) {
let matches = document.cookie.match(new RegExp(
"(?:^|; )" + name.replace(/([\.$?*|{}\(\)\[\]\\\/\+^])/g, '\\$1') + "=([^;]*)"
));
return matches ? decodeURIComponent(matches[1]) : null;
}
function ignore(reason) {
console.warn('[Plausible] Ignoring event because ' + reason);
}
function getUrl() {
return window.location.protocol + '//' + window.location.hostname + window.location.pathname + window.location.search;
}
function getSourceFromQueryParam() {
const result = window.location.search.match(/[?&](ref|source|utm_source)=([^?&]+)/);
return result ? result[2] : null
}
function getUserData() {
var userData = JSON.parse(getCookie('plausible_user'))
if (userData) {
return {
initial_referrer: userData.initial_referrer && decodeURIComponent(userData.initial_referrer),
initial_source: userData.initial_source && decodeURIComponent(userData.initial_source)
}
} else {
userData = {
initial_referrer: window.document.referrer || null,
initial_source: getSourceFromQueryParam(),
}
setCookie('plausible_user', JSON.stringify({
initial_referrer: userData.initial_referrer && encodeURIComponent(userData.initial_referrer),
initial_source: userData.initial_source && encodeURIComponent(userData.initial_source),
}))
return userData
}
}
function trigger(eventName, options) {
if (/^localhost$|^127(?:\.[0-9]+){0,2}\.[0-9]+$|^(?:0*\:)*?:?0*1$/.test(window.location.hostname)) return ignore('website is running locally');
if (window.location.protocol === 'file:') return ignore('website is running locally');
if (window.document.visibilityState === 'prerender') return ignore('document is prerendering');
var payload = CONFIG['trackAcquisition'] ? getUserData() : {}
payload.name = eventName
payload.url = getUrl()
payload.domain = CONFIG['domain']
payload.referrer = window.document.referrer || null
payload.source = getSourceFromQueryParam()
payload.user_agent = window.navigator.userAgent
payload.screen_width = window.innerWidth
var request = new XMLHttpRequest();
request.open('POST', plausibleHost + '/api/event', true);
request.setRequestHeader('Content-Type', 'text/plain');
request.send(JSON.stringify(payload));
request.onreadystatechange = function() {
if (request.readyState == XMLHttpRequest.DONE) {
options && options.callback && options.callback()
}
}
}
function page() {
trigger('pageview')
}
var his = window.history
if (his.pushState) {
var originalPushState = his['pushState']
his.pushState = function() {
originalPushState.apply(this, arguments)
page();
}
window.addEventListener('popstate', page)
}
const queue = (window.plausible && window.plausible.q) || []
window.plausible = trigger
for (var i = 0; i < queue.length; i++) {
trigger.apply(this, queue[i])
}
page()
} catch (e) {
new Image().src = plausibleHost + '/api/error?message=' + encodeURIComponent(e.message);
}
})(window, BASE_URL);

View File

@ -15,10 +15,7 @@ module.exports = (env, options) => ({
}, },
entry: { entry: {
'app': ['./js/app.js'], 'app': ['./js/app.js'],
'dashboard': ['./js/dashboard/mount.js'], 'dashboard': ['./js/dashboard/mount.js']
'p': ['./js/p.js'],
'analytics': ['./js/plausible.js'],
'plausible': ['./js/plausible.js']
}, },
output: { output: {
filename: '[name].js', filename: '[name].js',

View File

@ -1,4 +1,5 @@
cd $phoenix_dir cd $phoenix_dir
NODE_ENV=production npm --prefix ./assets run deploy NODE_ENV=production npm --prefix ./assets run deploy
npm --prefix ./tracker install && npm --prefix ./tracker run deploy
mix "${phoenix_ex}.digest" mix "${phoenix_ex}.digest"
mix "${phoenix_ex}.digest.clean" mix "${phoenix_ex}.digest.clean"

23
tracker/compile.js Normal file
View File

@ -0,0 +1,23 @@
const uglify = require("uglify-js");
const fs = require('fs')
const path = require('path')
const scheme = process.env.SCHEME || "http"
const host = process.env.HOST || "localhost"
const baseUrl = scheme + "://" + host
function relPath(segment) {
return path.join(__dirname, segment)
}
function compilefile(input, output) {
const code = fs.readFileSync(input)
.toString()
.replace('BASE_URL', "'" + baseUrl + "'")
const result = uglify.minify(code)
fs.writeFileSync(output, result.code)
}
compilefile(relPath('src/plausible.js'), relPath('../priv/static/js/plausible.js'))
compilefile(relPath('src/p.js'), relPath('../priv/static/js/p.js'))
fs.copyFileSync(relPath('../priv/static/js/plausible.js'), relPath('../priv/static/js/analytics.js'))

19
tracker/package-lock.json generated Normal file
View File

@ -0,0 +1,19 @@
{
"requires": true,
"lockfileVersion": 1,
"dependencies": {
"commander": {
"version": "2.20.3",
"resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz",
"integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ=="
},
"uglify-js": {
"version": "3.9.4",
"resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.9.4.tgz",
"integrity": "sha512-8RZBJq5smLOa7KslsNsVcSH+KOXf1uDU8yqLeNuVKwmT0T3FA0ZoXlinQfRad7SDcbZZRZE4ov+2v71EnxNyCA==",
"requires": {
"commander": "~2.20.3"
}
}
}
}

9
tracker/package.json Normal file
View File

@ -0,0 +1,9 @@
{
"scripts": {
"deploy": "node compile.js"
},
"license": "MIT",
"dependencies": {
"uglify-js": "^3.9.4"
}
}

127
tracker/src/p.js Normal file
View File

@ -0,0 +1,127 @@
(function(window, plausibleHost){
'use strict';
function setCookie(name,value) {
var date = new Date();
date.setTime(date.getTime() + (3*365*24*60*60*1000)); // 3 YEARS
var expires = "; expires=" + date.toUTCString();
document.cookie = name + "=" + (value || "") + expires + "; samesite=strict; path=/";
}
function getCookie(name) {
var matches = document.cookie.match(new RegExp(
"(?:^|; )" + name.replace(/([\.$?*|{}\(\)\[\]\\\/\+^])/g, '\\$1') + "=([^;]*)"
));
return matches ? decodeURIComponent(matches[1]) : null;
}
function ignore(reason) {
console.warn('[Plausible] Ignoring event because ' + reason);
}
function getUrl() {
return window.location.protocol + '//' + window.location.hostname + window.location.pathname + window.location.search;
}
function getSourceFromQueryParam() {
var result = window.location.search.match(/[?&](ref|source|utm_source)=([^?&]+)/);
return result ? result[2] : null
}
function getUserData() {
var userData = JSON.parse(getCookie('plausible_user'))
if (userData) {
return {
initial_referrer: userData.initial_referrer && decodeURIComponent(userData.initial_referrer),
initial_source: userData.initial_source && decodeURIComponent(userData.initial_source)
}
} else {
userData = {
initial_referrer: window.document.referrer || null,
initial_source: getSourceFromQueryParam(),
}
setCookie('plausible_user', JSON.stringify({
initial_referrer: userData.initial_referrer && encodeURIComponent(userData.initial_referrer),
initial_source: userData.initial_source && encodeURIComponent(userData.initial_source),
}))
return userData
}
}
function trigger(eventName, options) {
if (/^localhost$|^127(?:\.[0-9]+){0,2}\.[0-9]+$|^(?:0*\:)*?:?0*1$/.test(window.location.hostname)) return ignore('website is running locally');
if (window.location.protocol === 'file:') return ignore('website is running locally');
if (window.document.visibilityState === 'prerender') return ignore('document is prerendering');
var payload = CONFIG['trackAcquisition'] ? getUserData() : {}
payload.name = eventName
payload.url = getUrl()
payload.domain = CONFIG['domain']
payload.referrer = window.document.referrer || null
payload.source = getSourceFromQueryParam()
payload.user_agent = window.navigator.userAgent
payload.screen_width = window.innerWidth
var request = new XMLHttpRequest();
request.open('POST', plausibleHost + '/api/event', true);
request.setRequestHeader('Content-Type', 'text/plain');
request.send(JSON.stringify(payload));
request.onreadystatechange = function() {
if (request.readyState == XMLHttpRequest.DONE) {
options && options.callback && options.callback()
}
}
}
function page(options) {
trigger('pageview', options)
}
function trackPushState() {
var his = window.history
if (his.pushState) {
var originalFn = his['pushState']
his.pushState = function() {
originalFn.apply(this, arguments)
page();
}
}
window.addEventListener('popstate', page)
}
function configure(key, val) {
CONFIG[key] = val
}
try {
var CONFIG = {
domain: window.location.hostname
}
var functions = {
page: page,
trigger: trigger,
trackPushState: trackPushState,
configure: configure
}
var queue = window.plausible.q || []
window.plausible = function() {
var args = [].slice.call(arguments);
var funcName = args.shift();
functions[funcName].apply(this, args);
};
for (var i = 0; i < queue.length; i++) {
window.plausible.apply(this, queue[i])
}
} catch (e) {
new Image().src = plausibleHost + '/api/error?message=' + encodeURIComponent(e.message);
}
})(window, "https://plausible.io");

75
tracker/src/plausible.js Normal file
View File

@ -0,0 +1,75 @@
(function(window, plausibleHost){
'use strict';
var location = window.location
var document = window.document
var scriptEl = document.querySelector('[src*="' + plausibleHost +'"]')
var domainAttr = scriptEl && scriptEl.getAttribute('data-domain')
var CONFIG = {domain: domainAttr || location.hostname}
function ignore(reason) {
console.warn('[Plausible] Ignore event: ' + reason);
}
function getUrl() {
return location.protocol + '//' + location.hostname + location.pathname + location.search;
}
function getSourceFromQueryParam() {
var result = location.search.match(/[?&](ref|source|utm_source)=([^?&]+)/);
return result ? result[2] : null
}
function trigger(eventName, options) {
if (/^localhost$|^127(?:\.[0-9]+){0,2}\.[0-9]+$|^(?:0*\:)*?:?0*1$/.test(location.hostname) || location.protocol === 'file:') return ignore('running locally');
if (document.visibilityState === 'prerender') return ignore('prerendering');
var payload = {}
payload.name = eventName
payload.url = getUrl()
payload.domain = CONFIG['domain']
payload.referrer = document.referrer || null
payload.source = getSourceFromQueryParam()
payload.user_agent = window.navigator.userAgent
payload.screen_width = window.innerWidth
var request = new XMLHttpRequest();
request.open('POST', plausibleHost + '/api/event', true);
request.setRequestHeader('Content-Type', 'text/plain');
request.send(JSON.stringify(payload));
request.onreadystatechange = function() {
if (request.readyState == 4) {
options && options.callback && options.callback()
}
}
}
function page() {
trigger('pageview')
}
try {
var his = window.history
if (his.pushState) {
var originalPushState = his['pushState']
his.pushState = function() {
originalPushState.apply(this, arguments)
page();
}
window.addEventListener('popstate', page)
}
var queue = (window.plausible && window.plausible.q) || []
window.plausible = trigger
for (var i = 0; i < queue.length; i++) {
trigger.apply(this, queue[i])
}
page()
} catch (e) {
new Image().src = plausibleHost + '/api/error?message=' + encodeURIComponent(e.message);
}
})(window, BASE_URL);