mirror of
https://github.com/elyby/accounts-frontend.git
synced 2024-11-30 02:32:58 +05:30
Webpack 4
This commit is contained in:
parent
4783f1bad0
commit
fa46046f5f
52
package.json
52
package.json
@ -3,6 +3,7 @@
|
|||||||
"description": "",
|
"description": "",
|
||||||
"main": "src/index.js",
|
"main": "src/index.js",
|
||||||
"author": "SleepWalker <mybox@udf.su>",
|
"author": "SleepWalker <mybox@udf.su>",
|
||||||
|
"private": true,
|
||||||
"maintainers": [
|
"maintainers": [
|
||||||
{
|
{
|
||||||
"name": "ErickSkrauch",
|
"name": "ErickSkrauch",
|
||||||
@ -18,6 +19,10 @@
|
|||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=8.0.0"
|
"node": ">=8.0.0"
|
||||||
},
|
},
|
||||||
|
"workspaces": [
|
||||||
|
"webpack-utils",
|
||||||
|
"scripts"
|
||||||
|
],
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"start": "yarn run clean && yarn run build:dll && NODE_PATH=./src webpack-dev-server --progress --colors",
|
"start": "yarn run clean && yarn run build:dll && NODE_PATH=./src webpack-dev-server --progress --colors",
|
||||||
"clean": "rm -rf dist/",
|
"clean": "rm -rf dist/",
|
||||||
@ -26,8 +31,8 @@
|
|||||||
"lint": "eslint ./src",
|
"lint": "eslint ./src",
|
||||||
"flow": "flow",
|
"flow": "flow",
|
||||||
"i18n:collect": "babel-node ./scripts/i18n-collect.js",
|
"i18n:collect": "babel-node ./scripts/i18n-collect.js",
|
||||||
"i18n:push": "babel-node --presets flow --plugins transform-es2015-modules-commonjs ./scripts/i18n-crowdin.js push",
|
"i18n:push": "babel-node ./scripts/i18n-crowdin.js push",
|
||||||
"i18n:pull": "babel-node --presets flow --plugins transform-es2015-modules-commonjs ./scripts/i18n-crowdin.js pull",
|
"i18n:pull": "babel-node ./scripts/i18n-crowdin.js pull",
|
||||||
"build": "yarn run clean && yarn run build:webpack --progress",
|
"build": "yarn run clean && yarn run build:webpack --progress",
|
||||||
"build:install": "yarn install && check-node-version",
|
"build:install": "yarn install && check-node-version",
|
||||||
"build:webpack": "NODE_PATH=./src webpack --colors -p --bail",
|
"build:webpack": "NODE_PATH=./src webpack --colors -p --bail",
|
||||||
@ -88,24 +93,23 @@
|
|||||||
"babel-eslint": "^9.0.0",
|
"babel-eslint": "^9.0.0",
|
||||||
"babel-loader": "^8.0.0",
|
"babel-loader": "^8.0.0",
|
||||||
"babel-plugin-react-intl": "^2.0.0",
|
"babel-plugin-react-intl": "^2.0.0",
|
||||||
"bundle-loader": "^0.5.4",
|
|
||||||
"check-node-version": "^2.1.0",
|
"check-node-version": "^2.1.0",
|
||||||
"core-js": "3",
|
"core-js": "3",
|
||||||
"csp-webpack-plugin": "^1.0.2",
|
"csp-webpack-plugin": "^2.0.2",
|
||||||
"css-loader": "^0.28.0",
|
"css-loader": "^3.0.0",
|
||||||
|
"cssnano": "^4.1.10",
|
||||||
"enzyme": "^3.8.0",
|
"enzyme": "^3.8.0",
|
||||||
"enzyme-adapter-react-16": "^1.7.1",
|
"enzyme-adapter-react-16": "^1.7.1",
|
||||||
"eslint": "^4.0.0",
|
"eslint": "^4.0.0",
|
||||||
"eslint-plugin-flowtype": "^2.46.3",
|
"eslint-plugin-flowtype": "^2.46.3",
|
||||||
"eslint-plugin-react": "^7.3.0",
|
"eslint-plugin-react": "^7.3.0",
|
||||||
"exports-loader": "^0.6.3",
|
"exports-loader": "^0.7.0",
|
||||||
"extract-text-webpack-plugin": "^1.0.0",
|
"extract-text-webpack-plugin": "^3.0.2",
|
||||||
"file-loader": "^0.11.0",
|
"file-loader": "^4.0.0",
|
||||||
"flow-bin": "~0.102.0",
|
"flow-bin": "~0.102.0",
|
||||||
"fontgen-loader": "^0.2.1",
|
"html-loader": "^0.5.5",
|
||||||
"html-loader": "^0.4.3",
|
"html-webpack-plugin": "^3.2.0",
|
||||||
"html-webpack-plugin": "^2.0.0",
|
"imports-loader": "^0.8.0",
|
||||||
"imports-loader": "^0.7.0",
|
|
||||||
"jsdom": "^15.1.1",
|
"jsdom": "^15.1.1",
|
||||||
"json-loader": "^0.5.4",
|
"json-loader": "^0.5.4",
|
||||||
"karma": "^4.1.0",
|
"karma": "^4.1.0",
|
||||||
@ -114,26 +118,24 @@
|
|||||||
"karma-nyan-reporter": "^0.2.3",
|
"karma-nyan-reporter": "^0.2.3",
|
||||||
"karma-sinon": "^1.0.4",
|
"karma-sinon": "^1.0.4",
|
||||||
"karma-sourcemap-loader": "*",
|
"karma-sourcemap-loader": "*",
|
||||||
"karma-webpack": "^2.0.0",
|
"karma-webpack": "^4.0.2",
|
||||||
"loader-utils": "^1.0.0",
|
"loader-utils": "^1.0.0",
|
||||||
"mocha": "^6.1.4",
|
"mocha": "^6.1.4",
|
||||||
"node-sass": "^4.7.2",
|
"node-sass": "^4.7.2",
|
||||||
"postcss-import": "^9.0.0",
|
"postcss-import": "^12.0.1",
|
||||||
"postcss-loader": "^3.0.0",
|
"postcss-loader": "^3.0.0",
|
||||||
"postcss-scss": "^0.4.0",
|
"postcss-scss": "^2.0.0",
|
||||||
"postcss-url": "SleepWalker/postcss-url#switch-to-async-api",
|
"raw-loader": "^3.0.0",
|
||||||
"raw-loader": "^0.5.1",
|
|
||||||
"react-test-renderer": "^16.7.0",
|
"react-test-renderer": "^16.7.0",
|
||||||
"sass-loader": "^4.0.0",
|
"sass-loader": "^7.1.0",
|
||||||
"scripts": "file:./scripts",
|
|
||||||
"sinon": "^7.3.2",
|
"sinon": "^7.3.2",
|
||||||
"sitemap-webpack-plugin": "^0.5.1",
|
"sitemap-webpack-plugin": "^0.6.0",
|
||||||
"style-loader": "^0.18.0",
|
"style-loader": "^0.23.1",
|
||||||
"unexpected": "^11.6.1",
|
"unexpected": "^11.6.1",
|
||||||
"unexpected-sinon": "^10.5.1",
|
"unexpected-sinon": "^10.5.1",
|
||||||
"url-loader": "^0.5.7",
|
"url-loader": "^2.0.1",
|
||||||
"webpack": "^2.0.0",
|
"webpack": "^4.35.0",
|
||||||
"webpack-dev-server": "^2.0.0",
|
"webpack-cli": "^3.3.5",
|
||||||
"webpack-utils": "file:./webpack-utils"
|
"webpack-dev-server": "^3.7.2"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,3 +1,69 @@
|
|||||||
module.exports = {
|
/* eslint-env node */
|
||||||
plugins: {}
|
const path = require('path');
|
||||||
};
|
const loaderUtils = require('loader-utils');
|
||||||
|
const fileCache = {};
|
||||||
|
const isProduction = process.argv.some((arg) => arg === '-p');
|
||||||
|
const rootPath = path.resolve('./src');
|
||||||
|
|
||||||
|
module.exports = ({ webpack: loader }) => ({
|
||||||
|
syntax: 'postcss-scss',
|
||||||
|
plugins: {
|
||||||
|
'postcss-import': {
|
||||||
|
addModulesDirectories: ['./src'],
|
||||||
|
|
||||||
|
resolve: ((defaultResolve) => (url, basedir, importOptions) =>
|
||||||
|
defaultResolve(
|
||||||
|
// mainly to remove '~' from request
|
||||||
|
loaderUtils.urlToRequest(url),
|
||||||
|
basedir,
|
||||||
|
importOptions
|
||||||
|
))(require('postcss-import/lib/resolve-id')),
|
||||||
|
|
||||||
|
load: ((defaultLoad) => (filename, importOptions) => {
|
||||||
|
if (/\.font.(js|json)$/.test(filename)) {
|
||||||
|
// separately process calls to font loader
|
||||||
|
// e.g. `@import '~icons.font.json';`
|
||||||
|
if (!fileCache[filename] || !isProduction) {
|
||||||
|
// do not execute loader on the same file twice
|
||||||
|
// this is an overcome for a bug with ExtractTextPlugin, for isProduction === true
|
||||||
|
// when @imported files may be processed multiple times
|
||||||
|
fileCache[filename] = new Promise((resolve, reject) =>
|
||||||
|
loader.loadModule(filename, (err, source) => {
|
||||||
|
if (err) {
|
||||||
|
reject(err);
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
resolve(loader.exec(source, rootPath));
|
||||||
|
})
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return fileCache[filename];
|
||||||
|
}
|
||||||
|
|
||||||
|
return defaultLoad(filename, importOptions);
|
||||||
|
})(require('postcss-import/lib/load-content'))
|
||||||
|
},
|
||||||
|
// TODO: for some reason cssnano strips out @mixin declarations
|
||||||
|
// cssnano: {
|
||||||
|
// /**
|
||||||
|
// * TODO: cssnano options
|
||||||
|
// */
|
||||||
|
// // autoprefixer: {
|
||||||
|
// // add: true,
|
||||||
|
// // remove: true,
|
||||||
|
// // browsers: ['last 2 versions']
|
||||||
|
// // },
|
||||||
|
// // safe: true,
|
||||||
|
// // // отключаем минификацию цветов, что бы она не ломала такие выражения:
|
||||||
|
// // // composes: black from '~./buttons.scss';
|
||||||
|
// // colormin: false,
|
||||||
|
// // discardComments: {
|
||||||
|
// // removeAll: true
|
||||||
|
// // }
|
||||||
|
// preset: 'default'
|
||||||
|
// }
|
||||||
|
}
|
||||||
|
});
|
||||||
|
@ -5,6 +5,7 @@ import {sync as globSync} from 'glob';
|
|||||||
import {sync as mkdirpSync} from 'mkdirp';
|
import {sync as mkdirpSync} from 'mkdirp';
|
||||||
import chalk from 'chalk';
|
import chalk from 'chalk';
|
||||||
import prompt from 'prompt';
|
import prompt from 'prompt';
|
||||||
|
|
||||||
import localesMap from './../src/i18n/index.json';
|
import localesMap from './../src/i18n/index.json';
|
||||||
|
|
||||||
const MESSAGES_PATTERN = `${__dirname}/../dist/messages/**/*.json`;
|
const MESSAGES_PATTERN = `${__dirname}/../dist/messages/**/*.json`;
|
||||||
|
@ -10,11 +10,13 @@
|
|||||||
"author": "",
|
"author": "",
|
||||||
"license": "ISC",
|
"license": "ISC",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
"@babel/node": "^7.0.0",
|
||||||
"chalk": "^1.1.3",
|
"chalk": "^1.1.3",
|
||||||
"crowdin-api": "erickskrauch/crowdin-api#add_missed_methods_and_fix_files_uploading",
|
"crowdin-api": "erickskrauch/crowdin-api#add_missed_methods_and_fix_files_uploading",
|
||||||
|
"glob": "^7.1.4",
|
||||||
"iso-639-1": "^2.0.3",
|
"iso-639-1": "^2.0.3",
|
||||||
|
"mkdirp": "^0.5.1",
|
||||||
"multi-progress": "^2.0.0",
|
"multi-progress": "^2.0.0",
|
||||||
"node-babel": "^0.1.2",
|
|
||||||
"prompt": "^1.0.0"
|
"prompt": "^1.0.0"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -151,7 +151,7 @@ $lightBorderColor: #eee;
|
|||||||
}
|
}
|
||||||
|
|
||||||
.accountIcon {
|
.accountIcon {
|
||||||
composes: minecraft-character from 'components/ui/icons.scss';
|
composes: minecraft-character from '~components/ui/icons.scss';
|
||||||
|
|
||||||
float: left;
|
float: left;
|
||||||
|
|
||||||
@ -185,7 +185,7 @@ $lightBorderColor: #eee;
|
|||||||
}
|
}
|
||||||
|
|
||||||
.addIcon {
|
.addIcon {
|
||||||
composes: plus from 'components/ui/icons.scss';
|
composes: plus from '~components/ui/icons.scss';
|
||||||
|
|
||||||
color: $green;
|
color: $green;
|
||||||
position: relative;
|
position: relative;
|
||||||
@ -194,7 +194,7 @@ $lightBorderColor: #eee;
|
|||||||
}
|
}
|
||||||
|
|
||||||
.nextIcon {
|
.nextIcon {
|
||||||
composes: arrowRight from 'components/ui/icons.scss';
|
composes: arrowRight from '~components/ui/icons.scss';
|
||||||
|
|
||||||
position: relative;
|
position: relative;
|
||||||
float: right;
|
float: right;
|
||||||
@ -213,7 +213,7 @@ $lightBorderColor: #eee;
|
|||||||
}
|
}
|
||||||
|
|
||||||
.logoutIcon {
|
.logoutIcon {
|
||||||
composes: exit from 'components/ui/icons.scss';
|
composes: exit from '~components/ui/icons.scss';
|
||||||
|
|
||||||
color: #cdcdcd;
|
color: #cdcdcd;
|
||||||
float: right;
|
float: right;
|
||||||
|
@ -5,7 +5,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.descriptionImage {
|
.descriptionImage {
|
||||||
composes: envelope from 'components/ui/icons.scss';
|
composes: envelope from '~components/ui/icons.scss';
|
||||||
|
|
||||||
font-size: 100px;
|
font-size: 100px;
|
||||||
color: $blue;
|
color: $blue;
|
||||||
|
@ -20,12 +20,12 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.successBackground {
|
.successBackground {
|
||||||
composes: checkmark from 'components/ui/icons.scss';
|
composes: checkmark from '~components/ui/icons.scss';
|
||||||
@extend .iconBackground;
|
@extend .iconBackground;
|
||||||
}
|
}
|
||||||
|
|
||||||
.failBackground {
|
.failBackground {
|
||||||
composes: close from 'components/ui/icons.scss';
|
composes: close from '~components/ui/icons.scss';
|
||||||
@extend .iconBackground;
|
@extend .iconBackground;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -8,11 +8,11 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.login {
|
.login {
|
||||||
composes: email from 'components/auth/password/password.scss';
|
composes: email from '~components/auth/password/password.scss';
|
||||||
}
|
}
|
||||||
|
|
||||||
.editLogin {
|
.editLogin {
|
||||||
composes: pencil from 'components/ui/icons.scss';
|
composes: pencil from '~components/ui/icons.scss';
|
||||||
|
|
||||||
position: relative;
|
position: relative;
|
||||||
bottom: 1px;
|
bottom: 1px;
|
||||||
|
@ -5,7 +5,7 @@
|
|||||||
/* Form state */
|
/* Form state */
|
||||||
|
|
||||||
.contactForm {
|
.contactForm {
|
||||||
composes: popupWrapper from 'components/ui/popup/popup.scss';
|
composes: popupWrapper from '~components/ui/popup/popup.scss';
|
||||||
|
|
||||||
@include popupBounding(500px);
|
@include popupBounding(500px);
|
||||||
}
|
}
|
||||||
@ -46,13 +46,13 @@
|
|||||||
/* Success State */
|
/* Success State */
|
||||||
|
|
||||||
.successState {
|
.successState {
|
||||||
composes: popupWrapper from 'components/ui/popup/popup.scss';
|
composes: popupWrapper from '~components/ui/popup/popup.scss';
|
||||||
|
|
||||||
@include popupBounding(320px);
|
@include popupBounding(320px);
|
||||||
}
|
}
|
||||||
|
|
||||||
.successBody {
|
.successBody {
|
||||||
composes: body from 'components/ui/popup/popup.scss';
|
composes: body from '~components/ui/popup/popup.scss';
|
||||||
|
|
||||||
text-align: center;
|
text-align: center;
|
||||||
}
|
}
|
||||||
@ -64,7 +64,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.successIcon {
|
.successIcon {
|
||||||
composes: checkmark from 'components/ui/icons.scss';
|
composes: checkmark from '~components/ui/icons.scss';
|
||||||
|
|
||||||
font-size: 90px;
|
font-size: 90px;
|
||||||
color: #AAA;
|
color: #AAA;
|
||||||
|
@ -162,7 +162,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.appItemToggleIcon {
|
.appItemToggleIcon {
|
||||||
composes: arrowRight from 'components/ui/icons.scss';
|
composes: arrowRight from '~components/ui/icons.scss';
|
||||||
|
|
||||||
position: relative;
|
position: relative;
|
||||||
left: 0;
|
left: 0;
|
||||||
@ -208,7 +208,7 @@ $appDetailsContainerRightLeftPadding: 30px;
|
|||||||
}
|
}
|
||||||
|
|
||||||
.pencilIcon {
|
.pencilIcon {
|
||||||
composes: pencil from 'components/ui/icons.scss';
|
composes: pencil from '~components/ui/icons.scss';
|
||||||
|
|
||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
position: relative;
|
position: relative;
|
||||||
@ -254,7 +254,7 @@ $appDetailsContainerRightLeftPadding: 30px;
|
|||||||
}
|
}
|
||||||
|
|
||||||
.continueActionLink {
|
.continueActionLink {
|
||||||
composes: textLink from 'index.scss';
|
composes: textLink from '~index.scss';
|
||||||
|
|
||||||
font-family: $font-family-title;
|
font-family: $font-family-title;
|
||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
|
@ -14,7 +14,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.langTriggerIcon {
|
.langTriggerIcon {
|
||||||
composes: globe from 'components/ui/icons.scss';
|
composes: globe from '~components/ui/icons.scss';
|
||||||
|
|
||||||
position: relative;
|
position: relative;
|
||||||
bottom: 1px;
|
bottom: 1px;
|
||||||
|
@ -9,13 +9,13 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.languageSwitcher {
|
.languageSwitcher {
|
||||||
composes: popupWrapper from 'components/ui/popup/popup.scss';
|
composes: popupWrapper from '~components/ui/popup/popup.scss';
|
||||||
|
|
||||||
@include popupBounding(400px);
|
@include popupBounding(400px);
|
||||||
}
|
}
|
||||||
|
|
||||||
.languageSwitcherBody {
|
.languageSwitcherBody {
|
||||||
composes: body from 'components/ui/popup/popup.scss';
|
composes: body from '~components/ui/popup/popup.scss';
|
||||||
|
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
@ -32,7 +32,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.searchIcon {
|
.searchIcon {
|
||||||
composes: search from 'components/ui/icons.scss';
|
composes: search from '~components/ui/icons.scss';
|
||||||
|
|
||||||
position: absolute;
|
position: absolute;
|
||||||
top: 14px;
|
top: 14px;
|
||||||
@ -126,7 +126,7 @@ $languageListBorderStyle: 1px solid $languageListBorderColor;
|
|||||||
|
|
||||||
// Реализация радио кнопки. Когда у нас будет нормальный компонент радио кнопок, нужно будет перейти на него
|
// Реализация радио кнопки. Когда у нас будет нормальный компонент радио кнопок, нужно будет перейти на него
|
||||||
.languageCircle {
|
.languageCircle {
|
||||||
composes: checkmark from 'components/ui/icons.scss';
|
composes: checkmark from '~components/ui/icons.scss';
|
||||||
|
|
||||||
position: relative;
|
position: relative;
|
||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
@ -209,7 +209,7 @@ $languageListBorderStyle: 1px solid $languageListBorderColor;
|
|||||||
}
|
}
|
||||||
|
|
||||||
.improveTranslatesIcon {
|
.improveTranslatesIcon {
|
||||||
composes: translate from 'components/ui/icons.scss';
|
composes: translate from '~components/ui/icons.scss';
|
||||||
|
|
||||||
color: lighter($blue);
|
color: lighter($blue);
|
||||||
font-size: 22px;
|
font-size: 22px;
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
@import '~components/ui/popup/popup.scss';
|
@import '~components/ui/popup/popup.scss';
|
||||||
|
|
||||||
.requestPasswordForm {
|
.requestPasswordForm {
|
||||||
composes: popupWrapper from 'components/ui/popup/popup.scss';
|
composes: popupWrapper from '~components/ui/popup/popup.scss';
|
||||||
|
|
||||||
@include popupBounding(280px);
|
@include popupBounding(280px);
|
||||||
}
|
}
|
||||||
@ -11,7 +11,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.lockIcon {
|
.lockIcon {
|
||||||
composes: lock from 'components/ui/icons.scss';
|
composes: lock from '~components/ui/icons.scss';
|
||||||
|
|
||||||
font-size: 90px;
|
font-size: 90px;
|
||||||
color: #AAA;
|
color: #AAA;
|
||||||
|
@ -80,7 +80,7 @@ $formColumnWidth: 416px;
|
|||||||
}
|
}
|
||||||
|
|
||||||
.paramEditIcon {
|
.paramEditIcon {
|
||||||
composes: pencil from 'components/ui/icons.scss';
|
composes: pencil from '~components/ui/icons.scss';
|
||||||
|
|
||||||
color: $white;
|
color: $white;
|
||||||
transition: .4s;
|
transition: .4s;
|
||||||
|
@ -27,7 +27,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.backIcon {
|
.backIcon {
|
||||||
composes: arrowLeft from 'components/ui/icons.scss';
|
composes: arrowLeft from '~components/ui/icons.scss';
|
||||||
|
|
||||||
position: relative;
|
position: relative;
|
||||||
}
|
}
|
||||||
|
@ -55,7 +55,7 @@ $dropdownPadding: 15px;
|
|||||||
}
|
}
|
||||||
|
|
||||||
.toggleIcon {
|
.toggleIcon {
|
||||||
composes: selecter from 'components/ui/icons.scss';
|
composes: selecter from '~components/ui/icons.scss';
|
||||||
|
|
||||||
position: absolute;
|
position: absolute;
|
||||||
right: $dropdownPadding;
|
right: $dropdownPadding;
|
||||||
|
@ -284,7 +284,7 @@
|
|||||||
|
|
||||||
.mark {
|
.mark {
|
||||||
composes: markPosition;
|
composes: markPosition;
|
||||||
composes: checkmark from 'components/ui/icons.scss';
|
composes: checkmark from '~components/ui/icons.scss';
|
||||||
|
|
||||||
border: 2px #dcd8cd solid;
|
border: 2px #dcd8cd solid;
|
||||||
|
|
||||||
|
@ -23,7 +23,7 @@ $headerHeight: 60px;
|
|||||||
}
|
}
|
||||||
|
|
||||||
.headerControl {
|
.headerControl {
|
||||||
composes: black from 'components/ui/buttons.scss';
|
composes: black from '~components/ui/buttons.scss';
|
||||||
|
|
||||||
float: left;
|
float: left;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
@ -119,7 +119,7 @@ $bodyTopBottomPadding: 15px;
|
|||||||
}
|
}
|
||||||
|
|
||||||
.close {
|
.close {
|
||||||
composes: close from 'components/ui/icons.scss';
|
composes: close from '~components/ui/icons.scss';
|
||||||
|
|
||||||
position: absolute;
|
position: absolute;
|
||||||
right: 5px;
|
right: 5px;
|
||||||
|
@ -13,7 +13,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.activeAccountButton {
|
.activeAccountButton {
|
||||||
composes: green from 'components/ui/buttons.scss';
|
composes: green from '~components/ui/buttons.scss';
|
||||||
}
|
}
|
||||||
|
|
||||||
.activeAccountExpanded {
|
.activeAccountExpanded {
|
||||||
@ -31,7 +31,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.userIcon {
|
.userIcon {
|
||||||
composes: user from 'components/ui/icons.scss';
|
composes: user from '~components/ui/icons.scss';
|
||||||
|
|
||||||
position: relative;
|
position: relative;
|
||||||
bottom: 2px;
|
bottom: 2px;
|
||||||
@ -40,7 +40,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.expandIcon {
|
.expandIcon {
|
||||||
composes: caret from 'components/ui/icons.scss';
|
composes: caret from '~components/ui/icons.scss';
|
||||||
|
|
||||||
margin-left: 4px;
|
margin-left: 4px;
|
||||||
font-size: 6px;
|
font-size: 6px;
|
||||||
|
@ -52,7 +52,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.checkmark {
|
.checkmark {
|
||||||
composes: checkmark from 'components/ui/icons.scss';
|
composes: checkmark from '~components/ui/icons.scss';
|
||||||
|
|
||||||
color: lighter($green);
|
color: lighter($green);
|
||||||
font-size: 66px;
|
font-size: 66px;
|
||||||
|
@ -34,17 +34,17 @@ export default {
|
|||||||
messages: { [string]: string };
|
messages: { [string]: string };
|
||||||
}> {
|
}> {
|
||||||
const promises: Array<Promise<any>> = [
|
const promises: Array<Promise<any>> = [
|
||||||
import(/* webpackChunkName: "[request]-locale" */`react-intl/locale-data/${locale}.js`),
|
import(/* webpackChunkName: "locale-[request]" */`react-intl/locale-data/${locale}.js`),
|
||||||
import(/* webpackChunkName: "[request]-locale" */`i18n/${locale}.json`),
|
import(/* webpackChunkName: "locale-[request]" */`i18n/${locale}.json`),
|
||||||
];
|
];
|
||||||
|
|
||||||
if (needPolyfill) {
|
if (needPolyfill) {
|
||||||
promises.push(import(/* webpackChunkName: "[request]-intl-polyfill" */ 'intl'));
|
promises.push(import(/* webpackChunkName: "intl-polyfill" */'intl'));
|
||||||
promises.push(import(/* webpackChunkName: "[request]-intl-polyfill" */`intl/locale-data/jsonp/${locale}.js`));
|
promises.push(import(/* webpackChunkName: "intl-polyfill-[request]" */`intl/locale-data/jsonp/${locale}.js`));
|
||||||
}
|
}
|
||||||
|
|
||||||
return Promise.all(promises)
|
return Promise.all(promises)
|
||||||
.then(([localeData, messages]) => {
|
.then(([localeData, {default: messages}]) => {
|
||||||
addLocaleData(localeData);
|
addLocaleData(localeData);
|
||||||
|
|
||||||
return {locale, messages};
|
return {locale, messages};
|
||||||
|
@ -1,36 +0,0 @@
|
|||||||
// при использовании sass-loader теряется контекст в импортированных модулях
|
|
||||||
// из-за чего css-loader не может правильно обработать относительные url
|
|
||||||
//
|
|
||||||
// препроцессим урлы перед тем, как пропускать их через sass-loader
|
|
||||||
// урлы, начинающиеся с / будут оставлены как есть
|
|
||||||
|
|
||||||
const cssUrl = require('postcss-url');
|
|
||||||
const loaderUtils = require('loader-utils');
|
|
||||||
|
|
||||||
// /#.+$/ - strip #hash part of svg font url
|
|
||||||
const urlToRequest = (url) => loaderUtils.urlToRequest(url.replace(/\??#.+$/, ''), true);
|
|
||||||
const urlPostfix = (url) => {
|
|
||||||
var idx = url.indexOf('?#');
|
|
||||||
|
|
||||||
if (idx < 0) {
|
|
||||||
idx = url.indexOf('#');
|
|
||||||
}
|
|
||||||
|
|
||||||
return idx >= 0 ? url.slice(idx) : '';
|
|
||||||
};
|
|
||||||
|
|
||||||
module.exports = function(loader) {
|
|
||||||
return cssUrl({
|
|
||||||
url: (url, decl, from, dirname, to, options, result) =>
|
|
||||||
new Promise((resolve, reject) =>
|
|
||||||
loaderUtils.isUrlRequest(url) ? loader.loadModule(urlToRequest(url), (err, source) =>
|
|
||||||
err ? reject(err) : resolve(
|
|
||||||
loader.exec(`
|
|
||||||
var __webpack_public_path__ = '${loader.options.output.publicPath}';
|
|
||||||
${source}
|
|
||||||
`, dirname) + urlPostfix(url)
|
|
||||||
)
|
|
||||||
) : resolve(url)
|
|
||||||
)
|
|
||||||
});
|
|
||||||
};
|
|
201
webpack-utils/fontgen-loader.js
Normal file
201
webpack-utils/fontgen-loader.js
Normal file
@ -0,0 +1,201 @@
|
|||||||
|
/* eslint-env node */
|
||||||
|
/**
|
||||||
|
* Forked from
|
||||||
|
*
|
||||||
|
* https://github.com/DragonsInn/fontgen-loader
|
||||||
|
*/
|
||||||
|
|
||||||
|
const loaderUtils = require('loader-utils');
|
||||||
|
const fontgen = require('webfonts-generator');
|
||||||
|
const path = require('path');
|
||||||
|
const glob = require('glob');
|
||||||
|
|
||||||
|
const mimeTypes = {
|
||||||
|
eot: 'application/vnd.ms-fontobject',
|
||||||
|
svg: 'image/svg+xml',
|
||||||
|
ttf: 'application/x-font-ttf',
|
||||||
|
woff: 'application/font-woff'
|
||||||
|
};
|
||||||
|
|
||||||
|
function absolute(from, to) {
|
||||||
|
if (arguments.length < 2) {
|
||||||
|
return function(to) {
|
||||||
|
return path.resolve(from, to);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
return path.resolve(from, to);
|
||||||
|
}
|
||||||
|
|
||||||
|
function getFilesAndDeps(patterns, context) {
|
||||||
|
let files = [];
|
||||||
|
const filesDeps = [];
|
||||||
|
let directoryDeps = [];
|
||||||
|
|
||||||
|
function addFile(file) {
|
||||||
|
filesDeps.push(file);
|
||||||
|
files.push(absolute(context, file));
|
||||||
|
}
|
||||||
|
|
||||||
|
function addByGlob(globExp) {
|
||||||
|
const globOptions = { cwd: context };
|
||||||
|
|
||||||
|
const foundFiles = glob.sync(globExp, globOptions);
|
||||||
|
files = files.concat(foundFiles.map(absolute(context)));
|
||||||
|
|
||||||
|
const globDirs = glob.sync(`${path.dirname(globExp)}/`, globOptions);
|
||||||
|
directoryDeps = directoryDeps.concat(globDirs.map(absolute(context)));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Re-work the files array.
|
||||||
|
patterns.forEach((pattern) => {
|
||||||
|
if (glob.hasMagic(pattern)) {
|
||||||
|
addByGlob(pattern);
|
||||||
|
} else {
|
||||||
|
addFile(pattern);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
return {
|
||||||
|
files,
|
||||||
|
dependencies: {
|
||||||
|
directories: directoryDeps,
|
||||||
|
files: filesDeps
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = function(content) {
|
||||||
|
this.cacheable();
|
||||||
|
const params = loaderUtils.getOptions(this) || {};
|
||||||
|
let config;
|
||||||
|
try {
|
||||||
|
config = JSON.parse(content);
|
||||||
|
} catch (ex) {
|
||||||
|
config = this.exec(content, this.resourcePath);
|
||||||
|
}
|
||||||
|
|
||||||
|
config.__dirname = path.dirname(this.resourcePath);
|
||||||
|
|
||||||
|
// Sanity check
|
||||||
|
/*
|
||||||
|
if(typeof config.fontName != "string" || typeof config.files != "array") {
|
||||||
|
this.reportError("Typemismatch in your config. Verify your config for correct types.");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
const filesAndDeps = getFilesAndDeps(config.files, this.context);
|
||||||
|
filesAndDeps.dependencies.files.forEach(this.addDependency.bind(this));
|
||||||
|
filesAndDeps.dependencies.directories.forEach(
|
||||||
|
this.addContextDependency.bind(this)
|
||||||
|
);
|
||||||
|
config.files = filesAndDeps.files;
|
||||||
|
|
||||||
|
// With everything set up, let's make an ACTUAL config.
|
||||||
|
let formats = config.types || ['eot', 'woff', 'ttf', 'svg'];
|
||||||
|
if (formats.constructor !== Array) {
|
||||||
|
formats = [formats];
|
||||||
|
}
|
||||||
|
|
||||||
|
const fontconf = {
|
||||||
|
files: config.files,
|
||||||
|
fontName: config.fontName,
|
||||||
|
types: formats,
|
||||||
|
order: formats,
|
||||||
|
fontHeight: config.fontHeight || 1000, // Fixes conversion issues with small svgs
|
||||||
|
templateOptions: {
|
||||||
|
baseClass: config.baseClass || 'icon',
|
||||||
|
classPrefix: 'classPrefix' in config ? config.classPrefix : 'icon-'
|
||||||
|
},
|
||||||
|
dest: '',
|
||||||
|
writeFiles: false,
|
||||||
|
formatOptions: config.formatOptions || {}
|
||||||
|
};
|
||||||
|
|
||||||
|
// This originally was in the object notation itself.
|
||||||
|
// Unfortunately that actually broke my editor's syntax-highlighting...
|
||||||
|
// ... what a shame.
|
||||||
|
if (typeof config.rename == 'function') {
|
||||||
|
fontconf.rename = config.rename;
|
||||||
|
} else {
|
||||||
|
fontconf.rename = function(filePath) {
|
||||||
|
return path.basename(filePath, '.svg');
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
if (config.cssTemplate) {
|
||||||
|
fontconf.cssTemplate = absolute(this.context, config.cssTemplate);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (const option in config.templateOptions) {
|
||||||
|
if (config.templateOptions.hasOwnProperty(option)) {
|
||||||
|
fontconf.templateOptions[option] = config.templateOptions[option];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// svgicons2svgfont stuff
|
||||||
|
const keys = [
|
||||||
|
'fixedWidth',
|
||||||
|
'centerHorizontally',
|
||||||
|
'normalize',
|
||||||
|
'fontHeight',
|
||||||
|
'round',
|
||||||
|
'descent'
|
||||||
|
];
|
||||||
|
for (const x in keys) {
|
||||||
|
if (typeof config[keys[x]] != 'undefined') {
|
||||||
|
fontconf[keys[x]] = config[keys[x]];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const cb = this.async();
|
||||||
|
const opts = this._compiler.options;
|
||||||
|
const pub = opts.output.publicPath || '/';
|
||||||
|
const embed = !!params.embed;
|
||||||
|
|
||||||
|
if (fontconf.cssTemplate) {
|
||||||
|
this.addDependency(fontconf.cssTemplate);
|
||||||
|
}
|
||||||
|
|
||||||
|
fontgen(fontconf, (err, res) => {
|
||||||
|
if (err) {
|
||||||
|
return cb(err);
|
||||||
|
}
|
||||||
|
|
||||||
|
const urls = {};
|
||||||
|
|
||||||
|
for (const i in formats) {
|
||||||
|
const format = formats[i];
|
||||||
|
|
||||||
|
if (embed) {
|
||||||
|
urls[format] = `data:${
|
||||||
|
mimeTypes[format]
|
||||||
|
};charset=utf-8;base64,${new Buffer(res[format]).toString(
|
||||||
|
'base64'
|
||||||
|
)}`;
|
||||||
|
} else {
|
||||||
|
let filename
|
||||||
|
= config.fileName
|
||||||
|
|| params.fileName
|
||||||
|
|| '[hash]-[fontname][ext]';
|
||||||
|
filename = filename
|
||||||
|
.replace('[fontname]', fontconf.fontName)
|
||||||
|
.replace('[ext]', `.${format}`);
|
||||||
|
|
||||||
|
const url = loaderUtils.interpolateName(
|
||||||
|
this.context,
|
||||||
|
filename,
|
||||||
|
{
|
||||||
|
content: res[format]
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
urls[format] = path.join(pub, url).replace(/\\/g, '/');
|
||||||
|
this.emitFile(url, res[format]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const code = res.generateCss(urls);
|
||||||
|
|
||||||
|
cb(null, `module.exports = ${JSON.stringify(code)}`);
|
||||||
|
});
|
||||||
|
};
|
@ -3,19 +3,28 @@ module.exports = function(content) {
|
|||||||
content = JSON.parse(content);
|
content = JSON.parse(content);
|
||||||
|
|
||||||
const moduleId = this.context
|
const moduleId = this.context
|
||||||
.replace(this.options.resolve.root, '')
|
.replace(this.rootContext, '')
|
||||||
|
// TODO: can't find the way to strip out this path part programmatically
|
||||||
|
// this is a directory from resolve.modules config
|
||||||
|
// may be this may work: .replace(this._compiler.options.resolve.root, '')
|
||||||
|
.replace('src/', '')
|
||||||
.replace(/^\/|\/$/g, '')
|
.replace(/^\/|\/$/g, '')
|
||||||
.replace(/\//g, '.');
|
.replace(/\//g, '.');
|
||||||
|
|
||||||
content = JSON.stringify(Object.keys(content).reduce(function(translations, key) {
|
content = JSON.stringify(
|
||||||
translations[key] = {
|
Object.keys(content).reduce(
|
||||||
id: moduleId + '.' + key,
|
(translations, key) => ({
|
||||||
defaultMessage: content[key]
|
...translations,
|
||||||
};
|
[key]: {
|
||||||
|
id: `${moduleId}.${key}`,
|
||||||
|
defaultMessage: content[key]
|
||||||
|
}
|
||||||
|
}),
|
||||||
|
{}
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
return translations;
|
return `import { defineMessages } from 'react-intl';
|
||||||
}, {}));
|
|
||||||
|
|
||||||
return 'import { defineMessages } from \'react-intl\';'
|
export default defineMessages(${content})`;
|
||||||
+ 'export default defineMessages(' + content + ')';
|
|
||||||
};
|
};
|
||||||
|
@ -5,6 +5,8 @@
|
|||||||
"keywords": [],
|
"keywords": [],
|
||||||
"author": "",
|
"author": "",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"loader-utils": "^1.0.0"
|
"loader-utils": "^1.0.0",
|
||||||
|
"webfonts-generator": "^0.3.2",
|
||||||
|
"glob": "^6.0.2"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -3,29 +3,26 @@
|
|||||||
require('@babel/register');
|
require('@babel/register');
|
||||||
|
|
||||||
const path = require('path');
|
const path = require('path');
|
||||||
|
|
||||||
const webpack = require('webpack');
|
const webpack = require('webpack');
|
||||||
const loaderUtils = require('loader-utils');
|
|
||||||
const chalk = require('chalk');
|
const chalk = require('chalk');
|
||||||
const ExtractTextPlugin = require('extract-text-webpack-plugin');
|
const ExtractTextPlugin = require('extract-text-webpack-plugin');
|
||||||
const HtmlWebpackPlugin = require('html-webpack-plugin');
|
const HtmlWebpackPlugin = require('html-webpack-plugin');
|
||||||
const cssUrl = require('webpack-utils/cssUrl');
|
|
||||||
const cssImport = require('postcss-import');
|
|
||||||
const SitemapPlugin = require('sitemap-webpack-plugin').default;
|
const SitemapPlugin = require('sitemap-webpack-plugin').default;
|
||||||
const CSPPlugin = require('csp-webpack-plugin');
|
const CSPPlugin = require('csp-webpack-plugin');
|
||||||
const localeFlags = require('./src/components/i18n/localeFlags').default;
|
|
||||||
|
|
||||||
const SUPPORTED_LANGUAGES = Object.keys(require('./src/i18n/index.json'));
|
const SUPPORTED_LANGUAGES = Object.keys(require('./src/i18n/index.json'));
|
||||||
|
const localeFlags = require('./src/components/i18n/localeFlags').default;
|
||||||
const rootPath = path.resolve('./src');
|
const rootPath = path.resolve('./src');
|
||||||
const outputPath = path.join(__dirname, 'dist');
|
const outputPath = path.join(__dirname, 'dist');
|
||||||
|
|
||||||
const packageJson = require('./package.json');
|
const packageJson = require('./package.json');
|
||||||
|
|
||||||
let config = {};
|
let config = {};
|
||||||
try {
|
try {
|
||||||
config = require('./config/env.js');
|
config = require('./config/env.js');
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
console.log(chalk.yellow('\nCan not find config/env.js. Running with defaults\n\n'));
|
console.log(
|
||||||
|
chalk.yellow('\nCan not find config/env.js. Running with defaults\n\n')
|
||||||
|
);
|
||||||
|
|
||||||
if (err.code !== 'MODULE_NOT_FOUND') {
|
if (err.code !== 'MODULE_NOT_FOUND') {
|
||||||
console.error(err);
|
console.error(err);
|
||||||
@ -55,38 +52,11 @@ const isSilent = isCI || process.argv.some((arg) => /quiet/.test(arg));
|
|||||||
const isCspEnabled = false;
|
const isCspEnabled = false;
|
||||||
|
|
||||||
process.env.NODE_ENV = isProduction ? 'production' : 'development';
|
process.env.NODE_ENV = isProduction ? 'production' : 'development';
|
||||||
|
|
||||||
if (isTest) {
|
if (isTest) {
|
||||||
process.env.NODE_ENV = 'test';
|
process.env.NODE_ENV = 'test';
|
||||||
}
|
}
|
||||||
|
|
||||||
const CSS_CLASS_TEMPLATE = isProduction ? '[hash:base64:5]' : '[path][name]-[local]';
|
|
||||||
|
|
||||||
const fileCache = {};
|
|
||||||
|
|
||||||
const cssLoaderQuery = {
|
|
||||||
modules: true,
|
|
||||||
importLoaders: 2,
|
|
||||||
url: false,
|
|
||||||
localIdentName: CSS_CLASS_TEMPLATE,
|
|
||||||
|
|
||||||
/**
|
|
||||||
* cssnano options
|
|
||||||
*/
|
|
||||||
sourcemap: !isProduction,
|
|
||||||
autoprefixer: {
|
|
||||||
add: true,
|
|
||||||
remove: true,
|
|
||||||
browsers: ['last 2 versions']
|
|
||||||
},
|
|
||||||
safe: true,
|
|
||||||
// отключаем минификацию цветов, что бы она не ломала такие выражения:
|
|
||||||
// composes: black from './buttons.scss';
|
|
||||||
colormin: false,
|
|
||||||
discardComments: {
|
|
||||||
removeAll: true
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
const webpackConfig = {
|
const webpackConfig = {
|
||||||
cache: true,
|
cache: true,
|
||||||
|
|
||||||
@ -105,24 +75,33 @@ const webpackConfig = {
|
|||||||
extensions: ['.js', '.jsx', '.json']
|
extensions: ['.js', '.jsx', '.json']
|
||||||
},
|
},
|
||||||
|
|
||||||
externals: isTest ? {
|
externals: isTest
|
||||||
sinon: 'sinon',
|
? {
|
||||||
// http://airbnb.io/enzyme/docs/guides/webpack.html
|
sinon: 'sinon',
|
||||||
cheerio: 'window',
|
// http://airbnb.io/enzyme/docs/guides/webpack.html
|
||||||
'react/lib/ExecutionEnvironment': true,
|
cheerio: 'window',
|
||||||
'react/lib/ReactContext': true,
|
'react/lib/ExecutionEnvironment': true,
|
||||||
'react/addons': true
|
'react/lib/ReactContext': true,
|
||||||
} : {},
|
'react/addons': true
|
||||||
|
}
|
||||||
|
: {},
|
||||||
|
|
||||||
devtool: 'cheap-module-source-map',
|
devtool: 'cheap-module-source-map',
|
||||||
|
|
||||||
plugins: [
|
plugins: [
|
||||||
new webpack.DefinePlugin({
|
new webpack.DefinePlugin({
|
||||||
'window.SENTRY_CDN': config.sentryCdn ? JSON.stringify(config.sentryCdn) : undefined,
|
'window.SENTRY_CDN': config.sentryCdn
|
||||||
'window.GA_ID': config.ga && config.ga.id ? JSON.stringify(config.ga.id) : undefined,
|
? JSON.stringify(config.sentryCdn)
|
||||||
|
: undefined,
|
||||||
|
'window.GA_ID':
|
||||||
|
config.ga && config.ga.id
|
||||||
|
? JSON.stringify(config.ga.id)
|
||||||
|
: undefined,
|
||||||
'process.env': {
|
'process.env': {
|
||||||
NODE_ENV: JSON.stringify(process.env.NODE_ENV),
|
NODE_ENV: JSON.stringify(process.env.NODE_ENV),
|
||||||
APP_ENV: JSON.stringify(config.environment || process.env.NODE_ENV),
|
APP_ENV: JSON.stringify(
|
||||||
|
config.environment || process.env.NODE_ENV
|
||||||
|
),
|
||||||
__VERSION__: JSON.stringify(config.version || ''),
|
__VERSION__: JSON.stringify(config.version || ''),
|
||||||
__DEV__: !isProduction,
|
__DEV__: !isProduction,
|
||||||
__TEST__: isTest,
|
__TEST__: isTest,
|
||||||
@ -139,31 +118,37 @@ const webpackConfig = {
|
|||||||
minify: {
|
minify: {
|
||||||
collapseWhitespace: isProduction
|
collapseWhitespace: isProduction
|
||||||
},
|
},
|
||||||
isCspEnabled,
|
isCspEnabled
|
||||||
}),
|
|
||||||
new SitemapPlugin('https://account.ely.by', [
|
|
||||||
'/',
|
|
||||||
'/register',
|
|
||||||
'/resend-activation',
|
|
||||||
'/activation',
|
|
||||||
'/forgot-password',
|
|
||||||
'/rules',
|
|
||||||
], {
|
|
||||||
lastMod: true,
|
|
||||||
changeFreq: 'weekly',
|
|
||||||
}),
|
}),
|
||||||
|
new SitemapPlugin(
|
||||||
|
'https://account.ely.by',
|
||||||
|
[
|
||||||
|
'/',
|
||||||
|
'/register',
|
||||||
|
'/resend-activation',
|
||||||
|
'/activation',
|
||||||
|
'/forgot-password',
|
||||||
|
'/rules'
|
||||||
|
],
|
||||||
|
{
|
||||||
|
lastMod: true,
|
||||||
|
changeFreq: 'weekly'
|
||||||
|
}
|
||||||
|
),
|
||||||
new webpack.ProvidePlugin({
|
new webpack.ProvidePlugin({
|
||||||
React: 'react'
|
React: 'react'
|
||||||
}),
|
}),
|
||||||
// restrict webpack import context, to create chunks only for supported locales
|
// restrict webpack import context, to create chunks only for supported locales
|
||||||
// @see services/i18n.js
|
// @see services/i18n.js
|
||||||
new webpack.ContextReplacementPlugin(
|
new webpack.ContextReplacementPlugin(
|
||||||
/locale-data/, new RegExp(`/(${SUPPORTED_LANGUAGES.join('|')})\\.js`)
|
/locale-data/,
|
||||||
|
new RegExp(`/(${SUPPORTED_LANGUAGES.join('|')})\\.js`)
|
||||||
),
|
),
|
||||||
// @see components/i18n/localeFlags.js
|
// @see components/i18n/localeFlags.js
|
||||||
new webpack.ContextReplacementPlugin(
|
new webpack.ContextReplacementPlugin(
|
||||||
/flag-icon-css\/flags\/4x3/, new RegExp(`/(${localeFlags.getCountryList().join('|')})\\.svg`)
|
/flag-icon-css\/flags\/4x3/,
|
||||||
),
|
new RegExp(`/(${localeFlags.getCountryList().join('|')})\\.svg`)
|
||||||
|
)
|
||||||
],
|
],
|
||||||
|
|
||||||
module: {
|
module: {
|
||||||
@ -174,15 +159,28 @@ const webpackConfig = {
|
|||||||
'style-loader',
|
'style-loader',
|
||||||
{
|
{
|
||||||
loader: 'css-loader',
|
loader: 'css-loader',
|
||||||
options: cssLoaderQuery
|
options: {
|
||||||
|
modules: {
|
||||||
|
localIdentName: isProduction
|
||||||
|
? '[hash:base64:5]'
|
||||||
|
: '[path][name]-[local]'
|
||||||
|
},
|
||||||
|
importLoaders: 2,
|
||||||
|
sourceMap: !isProduction
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
loader: 'sass-loader',
|
||||||
|
options: {
|
||||||
|
sourceMap: !isProduction
|
||||||
|
}
|
||||||
},
|
},
|
||||||
'sass-loader',
|
|
||||||
{
|
{
|
||||||
loader: 'postcss-loader',
|
loader: 'postcss-loader',
|
||||||
options: {
|
options: {
|
||||||
syntax: 'postcss-scss',
|
|
||||||
ident: 'postcss',
|
ident: 'postcss',
|
||||||
plugins: postcss
|
sourceMap: !isProduction,
|
||||||
|
config: { path: __dirname }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
@ -213,12 +211,6 @@ const webpackConfig = {
|
|||||||
query: {
|
query: {
|
||||||
name: 'assets/fonts/[name].[ext]?[hash]'
|
name: 'assets/fonts/[name].[ext]?[hash]'
|
||||||
}
|
}
|
||||||
|
|
||||||
},
|
|
||||||
{
|
|
||||||
test: /\.json$/,
|
|
||||||
exclude: /(intl|font)\.json/,
|
|
||||||
loader: 'json-loader'
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
test: /\.html$/,
|
test: /\.html$/,
|
||||||
@ -226,20 +218,25 @@ const webpackConfig = {
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
test: /\.intl\.json$/,
|
test: /\.intl\.json$/,
|
||||||
loader: 'babel-loader!intl'
|
type: 'javascript/auto',
|
||||||
|
use: ['babel-loader', 'intl-loader']
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
// this is consumed by postcss-import
|
||||||
|
// @see postcss.config.js
|
||||||
test: /\.font\.(js|json)$/,
|
test: /\.font\.(js|json)$/,
|
||||||
loader: 'raw-loader!fontgen-loader'
|
type: 'javascript/auto',
|
||||||
|
use: ['fontgen-loader']
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
|
||||||
resolveLoader: {
|
resolveLoader: {
|
||||||
alias: {
|
alias: {
|
||||||
intl: path.resolve('webpack-utils/intl-loader')
|
'intl-loader': path.resolve('./webpack-utils/intl-loader'),
|
||||||
|
'fontgen-loader': path.resolve('./webpack-utils/fontgen-loader')
|
||||||
}
|
}
|
||||||
},
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
if (isProduction) {
|
if (isProduction) {
|
||||||
@ -248,7 +245,7 @@ if (isProduction) {
|
|||||||
// remove style-loader from chain and pass through ExtractTextPlugin
|
// remove style-loader from chain and pass through ExtractTextPlugin
|
||||||
loader.use = ExtractTextPlugin.extract({
|
loader.use = ExtractTextPlugin.extract({
|
||||||
fallbackLoader: loader.use[0], // style-loader
|
fallbackLoader: loader.use[0], // style-loader
|
||||||
loader: loader.use,
|
loader: loader.use
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@ -264,12 +261,11 @@ if (isProduction) {
|
|||||||
|
|
||||||
webpackConfig.devtool = 'hidden-source-map';
|
webpackConfig.devtool = 'hidden-source-map';
|
||||||
|
|
||||||
const ignoredPlugins = [
|
const ignoredPlugins = ['flag-icon-css'];
|
||||||
'flag-icon-css',
|
|
||||||
];
|
|
||||||
|
|
||||||
webpackConfig.entry.vendor = Object.keys(packageJson.dependencies)
|
webpackConfig.entry.vendor = Object.keys(packageJson.dependencies).filter(
|
||||||
.filter((module) => !ignoredPlugins.includes(module));
|
(module) => !ignoredPlugins.includes(module)
|
||||||
|
);
|
||||||
} else {
|
} else {
|
||||||
webpackConfig.plugins.push(
|
webpackConfig.plugins.push(
|
||||||
new webpack.DllReferencePlugin({
|
new webpack.DllReferencePlugin({
|
||||||
@ -280,50 +276,51 @@ if (isProduction) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (!isProduction && !isTest) {
|
if (!isProduction && !isTest) {
|
||||||
webpackConfig.plugins.push(
|
webpackConfig.plugins.push(new webpack.HotModuleReplacementPlugin());
|
||||||
new webpack.HotModuleReplacementPlugin(),
|
|
||||||
);
|
|
||||||
|
|
||||||
if (config.apiHost) {
|
webpackConfig.devServer = {
|
||||||
webpackConfig.devServer = {
|
host: 'localhost',
|
||||||
host: 'localhost',
|
port: 8080,
|
||||||
port: 8080,
|
proxy: config.apiHost && {
|
||||||
proxy: {
|
'/api': {
|
||||||
'/api': {
|
target: config.apiHost,
|
||||||
target: config.apiHost,
|
changeOrigin: true, // add host http-header, based on target
|
||||||
changeOrigin: true, // add host http-header, based on target
|
secure: false // allow self-signed certs
|
||||||
secure: false // allow self-signed certs
|
}
|
||||||
}
|
},
|
||||||
},
|
hot: true,
|
||||||
hot: true,
|
inline: true,
|
||||||
inline: true,
|
historyApiFallback: true
|
||||||
historyApiFallback: true
|
};
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isCspEnabled) {
|
if (isCspEnabled) {
|
||||||
webpackConfig.plugins.push(new CSPPlugin({
|
webpackConfig.plugins.push(
|
||||||
'default-src': '\'none\'',
|
new CSPPlugin({
|
||||||
'style-src': ['\'self\'', '\'unsafe-inline\''],
|
'default-src': '\'none\'',
|
||||||
'script-src': [
|
'style-src': ['\'self\'', '\'unsafe-inline\''],
|
||||||
'\'self\'',
|
'script-src': [
|
||||||
'\'nonce-edge-must-die\'',
|
'\'self\'',
|
||||||
'\'unsafe-inline\'',
|
'\'nonce-edge-must-die\'',
|
||||||
'https://www.google-analytics.com',
|
'\'unsafe-inline\'',
|
||||||
'https://recaptcha.net/recaptcha/',
|
'https://www.google-analytics.com',
|
||||||
'https://www.gstatic.com/recaptcha/',
|
'https://recaptcha.net/recaptcha/',
|
||||||
'https://www.gstatic.cn/recaptcha/',
|
'https://www.gstatic.com/recaptcha/',
|
||||||
],
|
'https://www.gstatic.cn/recaptcha/'
|
||||||
'img-src': ['\'self\'', 'data:', 'www.google-analytics.com'],
|
],
|
||||||
'font-src': ['\'self\'', 'data:'],
|
'img-src': ['\'self\'', 'data:', 'www.google-analytics.com'],
|
||||||
'connect-src': ['\'self\'', 'https://sentry.ely.by'].concat(isProduction ? [] : ['ws://localhost:8080']),
|
'font-src': ['\'self\'', 'data:'],
|
||||||
'frame-src': [
|
'connect-src': ['\'self\'', 'https://sentry.ely.by'].concat(
|
||||||
'https://www.google.com/recaptcha/',
|
isProduction ? [] : ['ws://localhost:8080']
|
||||||
'https://recaptcha.net/recaptcha/',
|
),
|
||||||
],
|
'frame-src': [
|
||||||
'report-uri': 'https://sentry.ely.by/api/2/csp-report/?sentry_key=088e7718236a4f91937a81fb319a93f6',
|
'https://www.google.com/recaptcha/',
|
||||||
}));
|
'https://recaptcha.net/recaptcha/'
|
||||||
|
],
|
||||||
|
'report-uri':
|
||||||
|
'https://sentry.ely.by/api/2/csp-report/?sentry_key=088e7718236a4f91937a81fb319a93f6'
|
||||||
|
})
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isDockerized) {
|
if (isDockerized) {
|
||||||
@ -351,41 +348,4 @@ if (isSilent) {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
function postcss() {
|
|
||||||
return [
|
|
||||||
cssImport({
|
|
||||||
path: rootPath,
|
|
||||||
|
|
||||||
resolve: ((defaultResolve) =>
|
|
||||||
(url, basedir, importOptions) =>
|
|
||||||
defaultResolve(loaderUtils.urlToRequest(url), basedir, importOptions)
|
|
||||||
)(require('postcss-import/lib/resolve-id')),
|
|
||||||
|
|
||||||
load: ((defaultLoad) =>
|
|
||||||
(filename, importOptions) => {
|
|
||||||
if (/\.font.(js|json)$/.test(filename)) {
|
|
||||||
if (!fileCache[filename] || !isProduction) {
|
|
||||||
// do not execute loader on the same file twice
|
|
||||||
// this is an overcome for a bug with ExtractTextPlugin, for isProduction === true
|
|
||||||
// when @imported files may be processed mutiple times
|
|
||||||
fileCache[filename] = new Promise((resolve, reject) =>
|
|
||||||
this.loadModule(filename, (err, source) =>
|
|
||||||
err ? reject(err) : resolve(this.exec(source, rootPath))
|
|
||||||
)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
return fileCache[filename];
|
|
||||||
}
|
|
||||||
|
|
||||||
return defaultLoad(filename, importOptions);
|
|
||||||
}
|
|
||||||
)(require('postcss-import/lib/load-content'))
|
|
||||||
}),
|
|
||||||
|
|
||||||
cssUrl(this)
|
|
||||||
];
|
|
||||||
}
|
|
||||||
|
|
||||||
module.exports = webpackConfig;
|
module.exports = webpackConfig;
|
||||||
|
@ -1,23 +1,26 @@
|
|||||||
/* eslint-env node */
|
/* eslint-env node */
|
||||||
|
|
||||||
const path = require('path');
|
const path = require('path');
|
||||||
|
|
||||||
const webpack = require('webpack');
|
const webpack = require('webpack');
|
||||||
|
|
||||||
const vendor = Object.keys(require('./package.json').dependencies);
|
const vendor = Object.keys(require('./package.json').dependencies);
|
||||||
|
|
||||||
const isProduction = process.argv.some((arg) => arg === '-p');
|
const isProduction = process.argv.some((arg) => arg === '-p');
|
||||||
|
const supportedLocales = require('./src/i18n/index.json');
|
||||||
const isTest = process.argv.some((arg) => arg.indexOf('karma') !== -1);
|
const isTest = process.argv.some((arg) => arg.indexOf('karma') !== -1);
|
||||||
|
|
||||||
process.env.NODE_ENV = 'development';
|
process.env.NODE_ENV = 'development';
|
||||||
|
|
||||||
if (isTest) {
|
if (isTest) {
|
||||||
process.env.NODE_ENV = 'test';
|
process.env.NODE_ENV = 'test';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (isProduction) {
|
||||||
|
throw new Error('Dll plugin should be used for dev mode only');
|
||||||
|
}
|
||||||
|
|
||||||
const outputPath = path.join(__dirname, 'dll');
|
const outputPath = path.join(__dirname, 'dll');
|
||||||
|
|
||||||
const webpackConfig = {
|
const webpackConfig = {
|
||||||
|
mode: 'development',
|
||||||
|
|
||||||
entry: {
|
entry: {
|
||||||
vendor: vendor.concat([
|
vendor: vendor.concat([
|
||||||
'core-js/library',
|
'core-js/library',
|
||||||
@ -26,12 +29,10 @@ const webpackConfig = {
|
|||||||
'redux-devtools-log-monitor',
|
'redux-devtools-log-monitor',
|
||||||
'react-transform-hmr',
|
'react-transform-hmr',
|
||||||
'react-transform-catch-errors',
|
'react-transform-catch-errors',
|
||||||
'redbox-react',
|
]).concat(
|
||||||
'react-intl/locale-data/en.js',
|
Object.keys(supportedLocales)
|
||||||
'react-intl/locale-data/ru.js',
|
.map((locale) => `react-intl/locale-data/${locale}.js`)
|
||||||
'react-intl/locale-data/be.js',
|
)
|
||||||
'react-intl/locale-data/uk.js'
|
|
||||||
])
|
|
||||||
},
|
},
|
||||||
|
|
||||||
output: {
|
output: {
|
||||||
@ -54,11 +55,7 @@ const webpackConfig = {
|
|||||||
name: '[name]',
|
name: '[name]',
|
||||||
path: path.join(outputPath, '[name].json')
|
path: path.join(outputPath, '[name].json')
|
||||||
})
|
})
|
||||||
].concat(isProduction ? [
|
]
|
||||||
new webpack.optimize.DedupePlugin(),
|
|
||||||
new webpack.optimize.OccurenceOrderPlugin(true),
|
|
||||||
new webpack.optimize.UglifyJsPlugin()
|
|
||||||
] : [])
|
|
||||||
};
|
};
|
||||||
|
|
||||||
module.exports = webpackConfig;
|
module.exports = webpackConfig;
|
||||||
|
Loading…
Reference in New Issue
Block a user