diff --git a/README.md b/README.md index d579b76..df5a260 100644 --- a/README.md +++ b/README.md @@ -25,25 +25,33 @@ Original idea was that Real Reality will be webpage where you can see mashup of 1. `git commit -m "my new great addition!"` 1. `git push` -Final extension structure -```bash -build -├── _locales -├── background.bundle.js -├── contentscript.bundle.js -├── css -├── fonts -├── images -└── manifest.json -``` ### Environment variables This project supports [dotenv](https://www.npmjs.com/package/dotenv) variables, by creating a `.env` file, you can put your secrets there. All `env` variables are then available in `./config/env.js` where you can export them and use in webpack `DefinePlugin` in `webpack.conf.js` + List of currently used environment variables within project + + * `GA_TRACKER_DEV` - Google Analytics TRACKER ID user in non-production builds + * `GA_TRACKER_PROD` - GA TRACKER ID for production * `GMAPS_API_KEY` - user your own please * `IPR_REST_API` - endpoint for real-reality + +### Building + +to compile a **production** version of the extension into \/**build** folder run + +``` +yarn build +``` + +or if you wanna specify custom GA +``` +GA_TRACKER_PROD=GA-XXXXX-X yarn build +``` + + Quick and dirty [source code of IPR Data Rest API Server](https://github.com/bedla/praguehacks-realreality). Main script is in **./src/js/contentscript.js** @@ -57,7 +65,3 @@ IPR API is backed by [IPR Data Rest API Server](https://github.com/realreality/r [Open Society Fund Praha / Fond Otakara Motejla](http://www.otevrenadata.cz/) for their [open data](https://en.wikipedia.org/wiki/Open_data) activities (like organizing Prague Hacks hackathon and other similar events, propagation the open data idea in goverment institutions..etc.). Samuel Simões - this extension is built on top of the scaffold [chrome-extension-webpack-boilerplate](https://github.com/samuelsimoes/chrome-extension-webpack-boilerplate) - - - - diff --git a/config/env.js b/config/env.js index 92f9c63..145ca89 100644 --- a/config/env.js +++ b/config/env.js @@ -1,11 +1,14 @@ // tiny wrapper with default env vars -const env = require('dotenv'); +const dotenv = require('dotenv') -env.load(); +dotenv.load() + +const env = process.env module.exports = { - - PORT: (process.env.PORT || 3000), - GMAPS_API_KEY: process.env.GMAPS_API_KEY, - IPR_REST_API: (process.env.IPR_REST_API || 'https://realreality.publicstaticvoidmain.cz/rest') -}; + GA_TRACKER_DEV: env.GA_TRACKER_DEV, + GA_TRACKER_PROD: env.GA_TRACKER_PROD, + PORT: (env.PORT || 3000), + GMAPS_API_KEY: env.GMAPS_API_KEY, + IPR_REST_API: (env.IPR_REST_API || 'https://realreality.publicstaticvoidmain.cz/rest'), +} diff --git a/package.json b/package.json index 0306b20..5bcc2de 100644 --- a/package.json +++ b/package.json @@ -5,7 +5,7 @@ "private": true, "scripts": { "cleanup": "rm -rf build", - "build": "npm run cleanup && node scripts/build-manifest.js && webpack -p", + "build": "node scripts/build-manifest.js && webpack --env=prod -p", "cz": "git-cz", "commitmsg": "validate-commit-msg", "lint": "eslint -c .eslintrc ./src/", diff --git a/scripts/webserver.js b/scripts/webserver.js index cba2ca0..6e0d114 100644 --- a/scripts/webserver.js +++ b/scripts/webserver.js @@ -3,7 +3,7 @@ const webpack = require('webpack') const path = require('path') const WriteFilePlugin = require('write-file-webpack-plugin') -const config = require('../webpack.config') +const config = require('../webpack.config')('dev') const env = require('./../config/env') // setup manifest diff --git a/src/js/background.js b/src/js/background.js index 5414552..f96c5cb 100644 --- a/src/js/background.js +++ b/src/js/background.js @@ -1,8 +1,18 @@ + +const debugAnalytics = process.env.GA_DEBUG === 'enabled' ? '_debug' : '' +const analyticsURL = `https://www.google-analytics.com/analytics${debugAnalytics}.js` + +;(function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){ + (i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o), + m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m) +})(window,document,'script', analyticsURL, 'ga') + +window.ga('create', process.env.GA_TRACKER_ID, 'auto') +window.ga('set', 'checkProtocolTask', function(){ /* nothing */ }) /** * Code that detects host page and switches icons in toolbar. */ chrome.runtime.onMessage.addListener(function (request, sender, sendResponse) { - console.log('request', request) if (request.switchIconOn) { chrome.browserAction.setIcon({ path: { @@ -12,4 +22,13 @@ chrome.runtime.onMessage.addListener(function (request, sender, sendResponse) { tabId: sender.tab.id, }) } -}) \ No newline at end of file + + if(request.eventType === 'EXTENSION_INIT') { + window.ga('send', { + hitType: 'pageview', + location: request.locationHref, + page: request.locationPathName, + title: request.documentTitle, + }) + } +}) diff --git a/src/js/contentscript.js b/src/js/contentscript.js index a9d9c6c..070e9c5 100644 --- a/src/js/contentscript.js +++ b/src/js/contentscript.js @@ -9,11 +9,10 @@ import { streetNamePredicate, addStyles } from './utils' import '../css/cssnormalize.scss' import '../css/panel.scss' -import panelTemplate from 'html-loader!../templates/panel.html' import App from './components/App.vue' -Vue.use(VueI18n) +Vue.use(VueI18n) RR.logInfo('contentscript loaded') chrome.runtime.sendMessage({ 'switchIconOn': true }) @@ -25,7 +24,7 @@ const initVueTranslations = () => { const [appLanguage] = languages RR.logDebug('Detected accepted languages: ', languages) RR.logInfo('Selected app language: ', appLanguage) - + const vueI18n = new VueI18n({ locale: appLanguage, fallbackLocale: 'en', @@ -43,11 +42,15 @@ const initVueTranslations = () => { const loadPanel = function(address) { RR.logDebug('Injecting panel (template) to page') - // html from panelTemplate holds the entry-point `#reality-panel-root` - $('body').append(panelTemplate) - RR.logDebug('Initializing view (replacing values in panel.html template)') - + $('body').append('
') + chrome.runtime.sendMessage({ + eventType: 'EXTENSION_INIT', + documentTitle: document.title, + locationHost: window.location.host, + locationHref: window.location.href, + locationPathName: window.location.pathname, + }) initVueTranslations() .then((i18n) => { Vue.config.devtools = true // does not work in extension diff --git a/src/manifest.json b/src/manifest.json index e0ca487..6432b37 100644 --- a/src/manifest.json +++ b/src/manifest.json @@ -33,6 +33,7 @@ "*://reality.idnes.cz/*" ], "js": [ + "vendor.bundle.js", "contentscript.bundle.js" ], "run_at": "document_end", @@ -48,7 +49,10 @@ "default_popup": "popup.html" }, "background": { - "scripts": ["background.bundle.js"] + "scripts": [ + "vendor.bundle.js", + "background.bundle.js" + ] }, - "content_security_policy": "script-src 'self' https://maps.googleapis.com; 'unsafe-eval' http://localhost:%PORT%; object-src 'self'" + "content_security_policy": "script-src 'self' https://www.google-analytics.com 'unsafe-eval'; object-src 'self'" } diff --git a/src/templates/panel.html b/src/templates/panel.html deleted file mode 100644 index 38929f7..0000000 --- a/src/templates/panel.html +++ /dev/null @@ -1,20 +0,0 @@ - -
- - - - - - diff --git a/webpack.config.js b/webpack.config.js index 4377366..a8e22db 100644 --- a/webpack.config.js +++ b/webpack.config.js @@ -10,74 +10,91 @@ const webpack = require('webpack') const env = require('./config/env') const basePath = fileName => path.join(__dirname, 'src', 'js', fileName) -module.exports = { - entry: { - background: basePath('background.js'), - contentscript: basePath('contentscript.js'), - popup: basePath('popup.js'), - }, - output: { - path: path.join(__dirname, 'build'), - filename: '[name].bundle.js', - }, - module: { - rules: [ - { - test: /\.vue$/, - loader: 'vue-loader', - }, - { - enforce: 'pre', - test: /\.js$/, - exclude: /node_modules/, - loader: 'eslint-loader', - }, - { - test: /\.js$/, - exclude: /node_modules/, - loader: 'babel-loader', - }, - { - test: /\.scss$/, - loader: ExtractTextPlugin.extract({ - fallback: 'style-loader', - use: ['css-loader', 'postcss-loader'], - }), - }, +module.exports = (profile) => { + const isProd = profile === 'prod' + const GA_TRACKER_ID = isProd ? env.GA_TRACKER_PROD : env.GA_TRACKER_DEV + + return { + entry: { + background: basePath('background.js'), + contentscript: basePath('contentscript.js'), + popup: basePath('popup.js'), + }, + output: { + path: path.join(__dirname, 'build'), + filename: '[name].bundle.js', + }, + module: { + rules: [ + { + test: /\.vue$/, + loader: 'vue-loader', + }, + { + enforce: 'pre', + test: /\.js$/, + exclude: /node_modules/, + loader: 'eslint-loader', + }, + { + test: /\.js$/, + exclude: /node_modules/, + loader: 'babel-loader', + }, + { + test: /\.scss$/, + loader: ExtractTextPlugin.extract({ + fallback: 'style-loader', + use: ['css-loader', 'postcss-loader'], + }), + }, + ], + }, + plugins: [ + new ProgressBarPlugin(), + new webpack.LoaderOptionsPlugin({ + options: { + postcss: [autoprefixer, precss], + excludeEntriesToHotReload: ['contentscript'], // a non-standard webpack opt, see usage in `./scripts/webserver.js` + }, + }), + // expose and write the allowed env vars on the compiled bundle + new webpack.DefinePlugin({ + 'process.env': { + GMAPS_API_KEY: JSON.stringify(env.GMAPS_API_KEY), + GA_DEBUG: JSON.stringify(isProd ? 'disabled': 'enabled'), + GA_TRACKER_ID: JSON.stringify(GA_TRACKER_ID), + IPR_REST_API: JSON.stringify(env.IPR_REST_API), + }, + }), + new HtmlWebpackPlugin({ + template: path.join(__dirname, 'src', 'popup.html'), + filename: 'popup.html', + chunks: ['popup'], + }), + new CopyWebpackPlugin([ + { from: path.join(__dirname, 'src/_locales'), to: '_locales'}, + { from: path.join(__dirname, 'src/images'), to: 'images'}, + { from: path.join(__dirname, 'node_modules/font-awesome/css/font-awesome.css'), to: 'css'}, + { from: path.join(__dirname, 'node_modules/font-awesome/fonts'), to: 'fonts'}, + ]), + new ExtractTextPlugin('./css/panel.css'), + new webpack.LoaderOptionsPlugin({ + debug: false, + minimize: true, + }), + new webpack.optimize.CommonsChunkPlugin({ + name: 'vendor', + minChunks: function(module){ + return module.context && module.context.indexOf('node_modules') !== -1 + }, + }), + ], - }, - plugins: [ - new ProgressBarPlugin(), - new webpack.LoaderOptionsPlugin({ - options: { - postcss: [autoprefixer, precss], - excludeEntriesToHotReload: ['contentscript'], // a non-standard webpack opt, see usage in `./scripts/webserver.js` - }, - }), - // expose and write the allowed env vars on the compiled bundle - new webpack.DefinePlugin({ - 'process.env': { - NODE_ENV: JSON.stringify(process.env.NODE_ENV || 'development'), - GMAPS_API_KEY: JSON.stringify(env.GMAPS_API_KEY), - IPR_REST_API: JSON.stringify(env.IPR_REST_API), + resolve: { + alias: { + 'vue$': 'vue/dist/vue.esm.js', }, - }), - new HtmlWebpackPlugin({ - template: path.join(__dirname, 'src', 'popup.html'), - filename: 'popup.html', - chunks: ['popup'], - }), - new CopyWebpackPlugin([ - { from: path.join(__dirname, 'src/_locales'), to: '_locales'}, - { from: path.join(__dirname, 'src/images'), to: 'images'}, - { from: path.join(__dirname, 'node_modules/font-awesome/css/font-awesome.css'), to: 'css'}, - { from: path.join(__dirname, 'node_modules/font-awesome/fonts'), to: 'fonts'}, - ]), - new ExtractTextPlugin('./css/panel.css'), - ], - resolve: { - alias: { - 'vue$': 'vue/dist/vue.common.js', }, - }, + } } diff --git a/yarn.lock b/yarn.lock index a9aa38b..f2dbf6a 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3596,6 +3596,10 @@ load-json-file@^1.0.0: pinkie-promise "^2.0.0" strip-bom "^2.0.0" +load-script@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/load-script/-/load-script-1.0.0.tgz#0491939e0bee5643ee494a7e3da3d2bac70c6ca4" + loader-fs-cache@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/loader-fs-cache/-/loader-fs-cache-1.0.1.tgz#56e0bf08bd9708b26a765b68509840c8dec9fdbc" @@ -5997,6 +6001,12 @@ void-elements@^2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/void-elements/-/void-elements-2.0.1.tgz#c066afb582bb1cb4128d60ea92392e94d5e9dbec" +vue-analytics@4.1.2: + version "4.1.2" + resolved "https://registry.yarnpkg.com/vue-analytics/-/vue-analytics-4.1.2.tgz#ea8be43810e3505c668f9b114fa5451baa435877" + dependencies: + load-script "^1.0.0" + vue-class-component@^5.0.0: version "5.0.1" resolved "https://registry.yarnpkg.com/vue-class-component/-/vue-class-component-5.0.1.tgz#feda06c3da266cee9064e224ba491e089923dce8"