improve and document developer setup (#161)

japanese commit
fixes #158
This commit is contained in:
Aleksei Gurianov
2018-07-13 09:54:12 +04:00
committed by GitHub
parent 62a5d7196e
commit a544aff6ac
17 changed files with 728 additions and 347 deletions
+2 -1
View File
@@ -62,9 +62,10 @@ FROM node:10.6-alpine as build-frontend
ARG CI
ARG SKIP_FRONTEND_TEST
ARG NODE_ENV=production
ADD web /srv/web
COPY --from=build-frontend-deps /srv/web/node_modules /srv/web/node_modules
ADD web /srv/web
RUN cd /srv/web && \
if [ -z "$SKIP_FRONTEND_TEST" ] ; then npx run-p lint test build ; \
else echo "skip frontend tests and lint" ; npm run build ; fi && \
+61 -48
View File
@@ -195,50 +195,9 @@ Admins/moderators should be defined in `docker-compose.yml` as a list of user ID
To get user id just login and click on your username or any other user you want to promote to admins.
It will expand login info and show full user ID.
### Setup on your website
### Frontend
Frontend part is building automatically along with backend if you use `docker-compose`.
For manual building:
* install [Node.js 8](https://nodejs.org/en/) or higher;
* install [NPM 6.1.0](https://www.npmjs.com/package/npm) or higher;
* run `npm install` inside `./web`;
* run `npm run build` there;
* result files will be saved in `./web/public`.
For development mode use `npm start` instead of `npm run build`.
In this case `webpack` will serve files using `webpack-dev-server` on `localhost:8080`.
URLs for development:
* `localhost:8080` — page with embedded script from `REMARK_URL` (default: `https://demo.remark42.com`);
* `localhost:8080/dev.html` — page with embedded script from local folder;
* `localhost:8080/last-comments.html` — page with embedded script for last comments;
* `localhost:8080/counter.html` — page with embedded script for counter with examples.
#### Testing
Also you can use fully functional local version to develop and test both frontend & backend.
To bring it up run:
```bash
docker-compose -f compose-dev-frontend.yml build
docker-compose -f compose-dev-frontend.yml up
```
It starts Remark42 on `localhost:8080`
and adds local OAuth2 provider “Dev”. To access UI demo page go to `localhost:8080/web`.
That `compose-dev.yml` (you can find it in the root of the project) also defines if default logged user admin or not.
By default, it will be the admin, and to switch it to regular user comment or remove `-ADMIN=dev_user` there. You can also select
any other user name from the login dialog.
#### Usage
##### Comments
#### Comments
It's a main widget which renders list of comments.
@@ -305,7 +264,7 @@ Add this snippet to the bottom of web page:
```html
<script>
var remark_config = {
site_id: 'YOUR_SITE_ID',
site_id: 'YOUR_SITE_ID',
};
(function() {
@@ -328,6 +287,62 @@ and it will use `data-url` attribute to define the page with comments.
Also script can uses `url` property from `remark_config` object, or `window.location.href` if nothing else is defined.
## Development
You can use fully functional local version to develop and test both frontend & backend.
To bring it up run:
```bash
# if you mainly work on backend
docker-compose -f compose-dev-backend.yml build
docker-compose -f compose-dev-backend.yml up
# if you mainly work on frontend
docker-compose -f compose-dev-frontend.yml build
docker-compose -f compose-dev-frontend.yml up
```
It starts Remark42 on `127.0.0.1:8080` and adds local OAuth2 provider “Dev”.
To access UI demo page go to `127.0.0.1:8080/web`.
By default, you would be logged in as `dev_user` which defined as admin.
You can tweak any of [supported parameters](#Parameters) in corresponded yml file.
Backend docker compose config by default skips running frontend related tests.
Frontend docker compose config by default skips running backend related tests and sets `NODE_ENV=development` for frontend build.
### Backend
Maybe instructions for local build here?
### Frontend
#### Build
* install [Node.js 8](https://nodejs.org/en/) or higher;
* install [NPM 6.1.0](https://www.npmjs.com/package/npm);
* run `npm install` inside `./web`;
* run `npm run build` there;
* result files will be saved in `./web/public`.
**Note** Running `npm install` will set up precommit hooks into your git repository.
It used to reformat your frontend code using `prettier` and lint with `eslint` before every commit.
#### Devserver
For local development mode with Hot Reloading use `npm start` instead of `npm run build`.
In this case `webpack` will serve files using `webpack-dev-server` on `localhost:9000`.
By visiting `127.0.0.1:9000/web` you will get a page with main comments widget.
communicating with demo server backend running on `https://demo.remark42.com`.
But you will not be able to login with any oauth providers due to security reasons.
You can attach to locally running backend by providing `REMARK_URL` environment variable.
```sh
npx cross-env REMARK_URL=http://127.0.0.1:8080 npm start
```
Developer build running by `webpack-dev-server` supports devtools for [React](https://github.com/facebook/react-devtools) and
[Redux](https://github.com/zalmoxisus/redux-devtools-extension).
## API
### Authorization
@@ -472,7 +487,6 @@ Sort can be `time`, `active` or `score`. Supported sort order with prefix -/+, i
_all admin calls require auth and admin privilege_
## Privacy
* Remark42 is trying to be very sensitive to any private or semi-private information.
@@ -487,7 +501,6 @@ _all admin calls require auth and admin privilege_
* Cookie lifespan can be restricted to session-only.
* All potentially sensitive data stored by remark42 hashed and encrypted.
## Technical details
* Data stored in [boltdb](https://github.com/coreos/bbolt) (embedded key/value database) files under `STORE_BOLT_PATH`
@@ -500,8 +513,8 @@ _all admin calls require auth and admin privilege_
* Request timeout set to 60sec
* Development mode (`--dev-password` set) allows to test remark42 without social login and with admin privileges. Adds basic-auth for username: `dev`, password: `${DEV_PASSWD}`. **should not be used in production deployment**
* User can vote for the comment multiple times but only to change the vote. Double-voting not allowed.
* User can edit comments in 5 mins window after creation.
* User can edit comments in 5 mins (configurable) window after creation.
* User ID hashed and prefixed by oauth provider name to avoid collisions and potential abuse.
* All avatars resized and cached locally to prevent rate limiters from google/github/facebook/yandex.
* All avatars resized and cached locally to prevent rate limiters from oauth providers.
* Images can be proxied (`IMG_PROXY=true`) to prevent mixed http/https.
* Docker build uses [publicly available](https://github.com/umputun/baseimage) base images.
+1 -1
View File
@@ -11,6 +11,7 @@ services:
dockerfile: Dockerfile
args:
- SKIP_BACKEND_TEST=true
# - NODE_ENV=development
image: umputun/remark42:dev
container_name: "remark42-dev"
@@ -38,6 +39,5 @@ services:
- ADMIN=dev_user # set admin flag for default user on local ouath2
volumes:
- ./var:/srv/var
# - ./web/public:/srv/web # uncomment to allow direct deployment of web parts
command: /srv/start.sh
-1
View File
@@ -36,6 +36,5 @@ services:
# - DEV_PASSWD=password # development mode, be careful!
volumes:
- ./var:/srv/var
#- ./web:/srv/web # uncomment to map web directory directly. It will propagate local changes to container without redeploy
command: /srv/start.sh
+4 -3
View File
@@ -2,9 +2,10 @@
echo "prepare environment"
# replace base url by REMARK_URL
sed -i "s|BASE_URL:\"[^\"]*\"|BASE_URL:\"${REMARK_URL}\"|g" /srv/web/*.js
sed -i "s|var baseurl = '[^']*';|var baseurl = '${REMARK_URL}';|g" /srv/web/*.html
# replace BASE_URL constant by REMARK_URL
sed -i "s|https://demo.remark42.com|${REMARK_URL}|g" /srv/web/*.js
# remove devtools attach helper. TODO: move to webpack loader
sed -i "/REMOVE-START/,/REMOVE-END/d" /srv/web/iframe.html
echo "start remark42 server"
+2 -2
View File
@@ -1,6 +1,6 @@
const BASE_URL = 'https://remark42.radio-t.com';
const BASE_URL = process.env.REMARK_URL;
const API_BASE = '/api/v1';
const NODE_ID = 'remark42';
const NODE_ID = process.env.REMARK_NODE;
const COUNTER_NODE_CLASSNAME = 'remark42__counter';
const COMMENT_NODE_CLASSNAME_PREFIX = 'remark42__comment-';
const LAST_COMMENTS_NODE_CLASSNAME = 'remark42__last-comments';
+2 -2
View File
@@ -35,7 +35,7 @@ function init() {
node.innerHTML = `
<iframe
src="${process.env.NODE_ENV === 'production' ? `${BASE_URL}/web` : ''}/iframe.html?${query}"
src="${BASE_URL}/web/iframe.html?${query}"
width="100%"
frameborder="0"
allowtransparency="true"
@@ -75,7 +75,7 @@ function init() {
`&id=${user.id}&name=${user.name}&picture=${user.picture || ''}&isDefaultPicture=${user.isDefaultPicture || 0}`;
this.node.innerHTML = `
<iframe
src="${process.env.NODE_ENV === 'production' ? `${BASE_URL}/web` : ''}/iframe.html?${queryUserInfo}"
src="${BASE_URL}/web/iframe.html?${queryUserInfo}"
width="100%"
height="100%"
frameborder="0"
+1
View File
@@ -1,6 +1,7 @@
/* eslint-disable no-console */
/** @jsx h */
import { h, render } from 'preact';
import 'preact/debug';
import { BASE_URL, DEFAULT_LAST_COMMENTS_MAX, LAST_COMMENTS_NODE_CLASSNAME } from './common/constants';
+1
View File
@@ -3,6 +3,7 @@
import loadPolyfills from 'common/polyfills';
import { h, render } from 'preact';
import 'preact/debug';
import { Provider } from 'preact-redux';
import Root from './components/root';
import UserInfo from 'components/user-info';
+5 -7
View File
@@ -21,14 +21,14 @@
<div class="container">
<p>
First counter with url from data-attribute:
<span class="remark42__counter" data-url="https://radio-t.com/p/2017/11/11/podcast-571/"></span>
(<a href="https://radio-t.com/p/2017/11/11/podcast-571/" target="_blank">note</a>)
<span class="remark42__counter" data-url="http://127.0.0.1:8080/web/"></span>
(<a href="http://127.0.0.1:8080/web/" target="_blank">note</a>)
</p>
<p>
Second counter with url from global remark config:
<span class="remark42__counter"></span>
(<a href="https://radio-t.com/p/2017/12/16/podcast-576/" target="_blank">note</a>)
(<a href="http://127.0.0.1:8080/web/" target="_blank">note</a>)
</p>
<p>
@@ -38,14 +38,12 @@
<script>
var remark_config = {
site_id: 'radiot',
url: 'https://radio-t.com/p/2017/12/16/podcast-576/'
site_id: 'remark',
};
(function() {
var d = document, s = d.createElement('script');
var baseurl = '';
s.src = baseurl + '/web/counter.js';
s.src = '/web/counter.js';
s.type = 'text/javascript';
(d.head || d.body).appendChild(s);
})();
-44
View File
@@ -1,44 +0,0 @@
<!DOCTYPE html>
<html lang="ru">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width,initial-scale=1">
<title>remark42</title>
<style>
body {
padding: 0;
margin: 0;
}
.container {
max-width: 800px;
margin: 5px;
}
@media (min-width: 768px) {
.container {
margin: 40px;
}
}
</style>
</head>
<body>
<div class="container">
<div id="remark42"></div>
</div>
<script>
var remark_config = {
site_id: 'radiot',
url: 'https://radio-t.com/p/2017/12/16/podcast-576/',
};
(function() {
var d = document, s = d.createElement('script');
s.src = '/embed.js';
(d.head || d.body).appendChild(s);
})();
</script>
</body>
</html>
+8 -1
View File
@@ -1,5 +1,5 @@
<!DOCTYPE html>
<html lang="ru">
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width,initial-scale=1">
@@ -75,6 +75,13 @@
</div>
</div>
<script>
/* REMOVE-START */
if (window.parent !== window) {
try {
window.__REACT_DEVTOOLS_GLOBAL_HOOK__ = window.parent.__REACT_DEVTOOLS_GLOBAL_HOOK__;
} catch (e){}
}
/* REMOVE-END */
var lastHeight = 0;
setInterval(function() {
if (document.body.offsetHeight !== lastHeight) {
+8 -2
View File
@@ -19,6 +19,13 @@
</head>
<body>
<div class="container">
<h1>Demo page</h1>
<p>To install widgets on your website, follow the <a href="https://github.com/umputun/remark#setup-on-your-website">instructions</a>.</p>
<p>See also</p>
<ul>
<li><a href="/web/last-comments.html">Last comments widget</a></li>
<li><a href="/web/counter.html">Counter widget</a></li>
</ul>
<div id="remark42"></div>
</div>
@@ -30,8 +37,7 @@
(function() {
var d = document, s = d.createElement('script');
var baseurl = 'https://demo.remark42.com/';
s.src = baseurl + '/web/embed.js';
s.src = '/web/embed.js';
s.type = 'text/javascript';
(d.head || d.body).appendChild(s);
})();
+2 -3
View File
@@ -24,13 +24,12 @@
<script>
var remark_config = {
site_id: 'radiot',
site_id: 'remark',
};
(function() {
var d = document, s = d.createElement('script');
var baseurl = '';
s.src = baseurl + '/web/last-comments.js';
s.src = '/web/last-comments.js';
s.type = 'text/javascript';
(d.head || d.body).appendChild(s);
})();
+599 -203
View File
File diff suppressed because it is too large Load Diff
+5 -6
View File
@@ -2,7 +2,7 @@
"name": "remark-ui",
"version": "0.1.0",
"scripts": {
"build": "cross-env NODE_ENV=production webpack --config ./webpack.config.js",
"build": "webpack --config ./webpack.config.js",
"start": "webpack-dev-server --progress --hot --inline --config ./webpack.config.js",
"lint": "eslint --ext=.js,.jsx .",
"test": "jest",
@@ -30,8 +30,6 @@
"babel-preset-env": "^1.7.0",
"clean-webpack-plugin": "^0.1.19",
"copy-webpack-plugin": "^4.5.1",
"core-js": "^2.5.7",
"cross-env": "^5.2.0",
"css-loader": "^0.28.11",
"eslint": "^4.19.1",
"eslint-config-prettier": "^2.9.0",
@@ -54,9 +52,7 @@
"postcss-simple-vars": "^4.1.0",
"postcss-url": "^6.3.1",
"postcss-wrap": "0.0.4",
"preact-redux": "^2.0.3",
"prettier": "^1.13.7",
"redux": "^4.0.0",
"style-loader": "^0.19.1",
"webpack": "^3.12.0",
"webpack-bundle-analyzer": "^2.13.1",
@@ -65,7 +61,10 @@
"dependencies": {
"axios": "^0.18.0",
"bem-react-helper": "^1.1.2",
"preact": "^8.2.9"
"core-js": "^2.5.7",
"preact": "^8.2.9",
"preact-redux": "^2.0.3",
"redux": "^4.0.0"
},
"eslintIgnore": [
"public"
+27 -23
View File
@@ -11,12 +11,13 @@ const Define = webpack.DefinePlugin;
const BundleAnalyze = require('webpack-bundle-analyzer').BundleAnalyzerPlugin;
const babelOptions = require('./babelOptions');
const { NODE_ID } = require('./app/common/constants');
const publicFolder = path.resolve(__dirname, 'public');
const env = process.env.NODE_ENV || 'dev';
const env = process.env.NODE_ENV || 'development';
const remarkUrl = process.env.REMARK_URL || 'https://demo.remark42.com';
const NODE_ID = 'remark42';
// let's log some env variables because we can
console.log(`NODE_ENV = ${env}`);
console.log(`REMARK_ENV = ${process.env.REMARK_URL}`);
const commonStyleLoaders = [
'css-loader',
@@ -39,6 +40,7 @@ const commonStyleLoaders = [
module.exports = {
context: __dirname,
devtool: env === 'development' ? 'source-map' : false,
entry: {
embed: './app/embed',
counter: './app/counter',
@@ -66,13 +68,10 @@ module.exports = {
},
{
test: /\.scss$/,
use:
env === 'production'
? ExtractText.extract({
fallback: 'style-loader',
use: commonStyleLoaders,
})
: ['style-loader', ...commonStyleLoaders],
use: ExtractText.extract({
fallback: 'style-loader',
use: commonStyleLoaders,
}),
},
{
test: /\.(png|jpg|jpeg|gif|svg)$/,
@@ -91,7 +90,9 @@ module.exports = {
b: 'bem-react-helper',
}),
new Define({
'process.env.NODE_ENV': JSON.stringify(process.env.NODE_ENV),
'process.env.NODE_ENV': JSON.stringify(env),
'process.env.REMARK_NODE': JSON.stringify(NODE_ID),
'process.env.REMARK_URL': env === 'production' ? JSON.stringify(remarkUrl) : 'window.location.origin',
}),
// TODO: we should add it only on demo serv
new Html({
@@ -110,15 +111,6 @@ module.exports = {
filename: 'last-comments.html',
inject: false,
}),
...(env === 'production'
? []
: [
new Html({
template: path.resolve(__dirname, 'dev.ejs'),
filename: 'dev.html',
inject: false,
}),
]),
new ExtractText({
filename: `remark.css`,
allChunks: true,
@@ -139,13 +131,25 @@ module.exports = {
]),
new Copy(['./iframe.html']),
],
watch: env === 'dev',
watchOptions: {
ignored: /(node_modules|\.vendor\.js$)/,
},
devServer: {
host: '0.0.0.0',
port: 8080,
host: 'localhost',
port: 9000,
contentBase: publicFolder,
publicPath: '/web',
proxy: {
'/api': {
target: remarkUrl,
logLevel: 'debug',
changeOrigin: true,
},
'/auth': {
target: remarkUrl,
logLevel: 'debug',
changeOrigin: true,
},
},
},
};