mirror of
https://github.com/elyby/accounts-frontend.git
synced 2024-11-09 17:42:03 +05:30
Webpack 4
This commit is contained in:
parent
4783f1bad0
commit
fa46046f5f
52
package.json
52
package.json
@ -3,6 +3,7 @@
|
||||
"description": "",
|
||||
"main": "src/index.js",
|
||||
"author": "SleepWalker <mybox@udf.su>",
|
||||
"private": true,
|
||||
"maintainers": [
|
||||
{
|
||||
"name": "ErickSkrauch",
|
||||
@ -18,6 +19,10 @@
|
||||
"engines": {
|
||||
"node": ">=8.0.0"
|
||||
},
|
||||
"workspaces": [
|
||||
"webpack-utils",
|
||||
"scripts"
|
||||
],
|
||||
"scripts": {
|
||||
"start": "yarn run clean && yarn run build:dll && NODE_PATH=./src webpack-dev-server --progress --colors",
|
||||
"clean": "rm -rf dist/",
|
||||
@ -26,8 +31,8 @@
|
||||
"lint": "eslint ./src",
|
||||
"flow": "flow",
|
||||
"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:pull": "babel-node --presets flow --plugins transform-es2015-modules-commonjs ./scripts/i18n-crowdin.js pull",
|
||||
"i18n:push": "babel-node ./scripts/i18n-crowdin.js push",
|
||||
"i18n:pull": "babel-node ./scripts/i18n-crowdin.js pull",
|
||||
"build": "yarn run clean && yarn run build:webpack --progress",
|
||||
"build:install": "yarn install && check-node-version",
|
||||
"build:webpack": "NODE_PATH=./src webpack --colors -p --bail",
|
||||
@ -88,24 +93,23 @@
|
||||
"babel-eslint": "^9.0.0",
|
||||
"babel-loader": "^8.0.0",
|
||||
"babel-plugin-react-intl": "^2.0.0",
|
||||
"bundle-loader": "^0.5.4",
|
||||
"check-node-version": "^2.1.0",
|
||||
"core-js": "3",
|
||||
"csp-webpack-plugin": "^1.0.2",
|
||||
"css-loader": "^0.28.0",
|
||||
"csp-webpack-plugin": "^2.0.2",
|
||||
"css-loader": "^3.0.0",
|
||||
"cssnano": "^4.1.10",
|
||||
"enzyme": "^3.8.0",
|
||||
"enzyme-adapter-react-16": "^1.7.1",
|
||||
"eslint": "^4.0.0",
|
||||
"eslint-plugin-flowtype": "^2.46.3",
|
||||
"eslint-plugin-react": "^7.3.0",
|
||||
"exports-loader": "^0.6.3",
|
||||
"extract-text-webpack-plugin": "^1.0.0",
|
||||
"file-loader": "^0.11.0",
|
||||
"exports-loader": "^0.7.0",
|
||||
"extract-text-webpack-plugin": "^3.0.2",
|
||||
"file-loader": "^4.0.0",
|
||||
"flow-bin": "~0.102.0",
|
||||
"fontgen-loader": "^0.2.1",
|
||||
"html-loader": "^0.4.3",
|
||||
"html-webpack-plugin": "^2.0.0",
|
||||
"imports-loader": "^0.7.0",
|
||||
"html-loader": "^0.5.5",
|
||||
"html-webpack-plugin": "^3.2.0",
|
||||
"imports-loader": "^0.8.0",
|
||||
"jsdom": "^15.1.1",
|
||||
"json-loader": "^0.5.4",
|
||||
"karma": "^4.1.0",
|
||||
@ -114,26 +118,24 @@
|
||||
"karma-nyan-reporter": "^0.2.3",
|
||||
"karma-sinon": "^1.0.4",
|
||||
"karma-sourcemap-loader": "*",
|
||||
"karma-webpack": "^2.0.0",
|
||||
"karma-webpack": "^4.0.2",
|
||||
"loader-utils": "^1.0.0",
|
||||
"mocha": "^6.1.4",
|
||||
"node-sass": "^4.7.2",
|
||||
"postcss-import": "^9.0.0",
|
||||
"postcss-import": "^12.0.1",
|
||||
"postcss-loader": "^3.0.0",
|
||||
"postcss-scss": "^0.4.0",
|
||||
"postcss-url": "SleepWalker/postcss-url#switch-to-async-api",
|
||||
"raw-loader": "^0.5.1",
|
||||
"postcss-scss": "^2.0.0",
|
||||
"raw-loader": "^3.0.0",
|
||||
"react-test-renderer": "^16.7.0",
|
||||
"sass-loader": "^4.0.0",
|
||||
"scripts": "file:./scripts",
|
||||
"sass-loader": "^7.1.0",
|
||||
"sinon": "^7.3.2",
|
||||
"sitemap-webpack-plugin": "^0.5.1",
|
||||
"style-loader": "^0.18.0",
|
||||
"sitemap-webpack-plugin": "^0.6.0",
|
||||
"style-loader": "^0.23.1",
|
||||
"unexpected": "^11.6.1",
|
||||
"unexpected-sinon": "^10.5.1",
|
||||
"url-loader": "^0.5.7",
|
||||
"webpack": "^2.0.0",
|
||||
"webpack-dev-server": "^2.0.0",
|
||||
"webpack-utils": "file:./webpack-utils"
|
||||
"url-loader": "^2.0.1",
|
||||
"webpack": "^4.35.0",
|
||||
"webpack-cli": "^3.3.5",
|
||||
"webpack-dev-server": "^3.7.2"
|
||||
}
|
||||
}
|
||||
|
@ -1,3 +1,69 @@
|
||||
module.exports = {
|
||||
plugins: {}
|
||||
};
|
||||
/* eslint-env node */
|
||||
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 chalk from 'chalk';
|
||||
import prompt from 'prompt';
|
||||
|
||||
import localesMap from './../src/i18n/index.json';
|
||||
|
||||
const MESSAGES_PATTERN = `${__dirname}/../dist/messages/**/*.json`;
|
||||
|
@ -10,11 +10,13 @@
|
||||
"author": "",
|
||||
"license": "ISC",
|
||||
"dependencies": {
|
||||
"@babel/node": "^7.0.0",
|
||||
"chalk": "^1.1.3",
|
||||
"crowdin-api": "erickskrauch/crowdin-api#add_missed_methods_and_fix_files_uploading",
|
||||
"glob": "^7.1.4",
|
||||
"iso-639-1": "^2.0.3",
|
||||
"mkdirp": "^0.5.1",
|
||||
"multi-progress": "^2.0.0",
|
||||
"node-babel": "^0.1.2",
|
||||
"prompt": "^1.0.0"
|
||||
}
|
||||
}
|
||||
|
@ -151,7 +151,7 @@ $lightBorderColor: #eee;
|
||||
}
|
||||
|
||||
.accountIcon {
|
||||
composes: minecraft-character from 'components/ui/icons.scss';
|
||||
composes: minecraft-character from '~components/ui/icons.scss';
|
||||
|
||||
float: left;
|
||||
|
||||
@ -185,7 +185,7 @@ $lightBorderColor: #eee;
|
||||
}
|
||||
|
||||
.addIcon {
|
||||
composes: plus from 'components/ui/icons.scss';
|
||||
composes: plus from '~components/ui/icons.scss';
|
||||
|
||||
color: $green;
|
||||
position: relative;
|
||||
@ -194,7 +194,7 @@ $lightBorderColor: #eee;
|
||||
}
|
||||
|
||||
.nextIcon {
|
||||
composes: arrowRight from 'components/ui/icons.scss';
|
||||
composes: arrowRight from '~components/ui/icons.scss';
|
||||
|
||||
position: relative;
|
||||
float: right;
|
||||
@ -213,7 +213,7 @@ $lightBorderColor: #eee;
|
||||
}
|
||||
|
||||
.logoutIcon {
|
||||
composes: exit from 'components/ui/icons.scss';
|
||||
composes: exit from '~components/ui/icons.scss';
|
||||
|
||||
color: #cdcdcd;
|
||||
float: right;
|
||||
|
@ -5,7 +5,7 @@
|
||||
}
|
||||
|
||||
.descriptionImage {
|
||||
composes: envelope from 'components/ui/icons.scss';
|
||||
composes: envelope from '~components/ui/icons.scss';
|
||||
|
||||
font-size: 100px;
|
||||
color: $blue;
|
||||
|
@ -20,12 +20,12 @@
|
||||
}
|
||||
|
||||
.successBackground {
|
||||
composes: checkmark from 'components/ui/icons.scss';
|
||||
composes: checkmark from '~components/ui/icons.scss';
|
||||
@extend .iconBackground;
|
||||
}
|
||||
|
||||
.failBackground {
|
||||
composes: close from 'components/ui/icons.scss';
|
||||
composes: close from '~components/ui/icons.scss';
|
||||
@extend .iconBackground;
|
||||
}
|
||||
|
||||
|
@ -8,11 +8,11 @@
|
||||
}
|
||||
|
||||
.login {
|
||||
composes: email from 'components/auth/password/password.scss';
|
||||
composes: email from '~components/auth/password/password.scss';
|
||||
}
|
||||
|
||||
.editLogin {
|
||||
composes: pencil from 'components/ui/icons.scss';
|
||||
composes: pencil from '~components/ui/icons.scss';
|
||||
|
||||
position: relative;
|
||||
bottom: 1px;
|
||||
|
@ -5,7 +5,7 @@
|
||||
/* Form state */
|
||||
|
||||
.contactForm {
|
||||
composes: popupWrapper from 'components/ui/popup/popup.scss';
|
||||
composes: popupWrapper from '~components/ui/popup/popup.scss';
|
||||
|
||||
@include popupBounding(500px);
|
||||
}
|
||||
@ -46,13 +46,13 @@
|
||||
/* Success State */
|
||||
|
||||
.successState {
|
||||
composes: popupWrapper from 'components/ui/popup/popup.scss';
|
||||
composes: popupWrapper from '~components/ui/popup/popup.scss';
|
||||
|
||||
@include popupBounding(320px);
|
||||
}
|
||||
|
||||
.successBody {
|
||||
composes: body from 'components/ui/popup/popup.scss';
|
||||
composes: body from '~components/ui/popup/popup.scss';
|
||||
|
||||
text-align: center;
|
||||
}
|
||||
@ -64,7 +64,7 @@
|
||||
}
|
||||
|
||||
.successIcon {
|
||||
composes: checkmark from 'components/ui/icons.scss';
|
||||
composes: checkmark from '~components/ui/icons.scss';
|
||||
|
||||
font-size: 90px;
|
||||
color: #AAA;
|
||||
|
@ -162,7 +162,7 @@
|
||||
}
|
||||
|
||||
.appItemToggleIcon {
|
||||
composes: arrowRight from 'components/ui/icons.scss';
|
||||
composes: arrowRight from '~components/ui/icons.scss';
|
||||
|
||||
position: relative;
|
||||
left: 0;
|
||||
@ -208,7 +208,7 @@ $appDetailsContainerRightLeftPadding: 30px;
|
||||
}
|
||||
|
||||
.pencilIcon {
|
||||
composes: pencil from 'components/ui/icons.scss';
|
||||
composes: pencil from '~components/ui/icons.scss';
|
||||
|
||||
font-size: 14px;
|
||||
position: relative;
|
||||
@ -254,7 +254,7 @@ $appDetailsContainerRightLeftPadding: 30px;
|
||||
}
|
||||
|
||||
.continueActionLink {
|
||||
composes: textLink from 'index.scss';
|
||||
composes: textLink from '~index.scss';
|
||||
|
||||
font-family: $font-family-title;
|
||||
font-size: 14px;
|
||||
|
@ -14,7 +14,7 @@
|
||||
}
|
||||
|
||||
.langTriggerIcon {
|
||||
composes: globe from 'components/ui/icons.scss';
|
||||
composes: globe from '~components/ui/icons.scss';
|
||||
|
||||
position: relative;
|
||||
bottom: 1px;
|
||||
|
@ -9,13 +9,13 @@
|
||||
}
|
||||
|
||||
.languageSwitcher {
|
||||
composes: popupWrapper from 'components/ui/popup/popup.scss';
|
||||
composes: popupWrapper from '~components/ui/popup/popup.scss';
|
||||
|
||||
@include popupBounding(400px);
|
||||
}
|
||||
|
||||
.languageSwitcherBody {
|
||||
composes: body from 'components/ui/popup/popup.scss';
|
||||
composes: body from '~components/ui/popup/popup.scss';
|
||||
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
@ -32,7 +32,7 @@
|
||||
}
|
||||
|
||||
.searchIcon {
|
||||
composes: search from 'components/ui/icons.scss';
|
||||
composes: search from '~components/ui/icons.scss';
|
||||
|
||||
position: absolute;
|
||||
top: 14px;
|
||||
@ -126,7 +126,7 @@ $languageListBorderStyle: 1px solid $languageListBorderColor;
|
||||
|
||||
// Реализация радио кнопки. Когда у нас будет нормальный компонент радио кнопок, нужно будет перейти на него
|
||||
.languageCircle {
|
||||
composes: checkmark from 'components/ui/icons.scss';
|
||||
composes: checkmark from '~components/ui/icons.scss';
|
||||
|
||||
position: relative;
|
||||
box-sizing: border-box;
|
||||
@ -209,7 +209,7 @@ $languageListBorderStyle: 1px solid $languageListBorderColor;
|
||||
}
|
||||
|
||||
.improveTranslatesIcon {
|
||||
composes: translate from 'components/ui/icons.scss';
|
||||
composes: translate from '~components/ui/icons.scss';
|
||||
|
||||
color: lighter($blue);
|
||||
font-size: 22px;
|
||||
|
@ -1,7 +1,7 @@
|
||||
@import '~components/ui/popup/popup.scss';
|
||||
|
||||
.requestPasswordForm {
|
||||
composes: popupWrapper from 'components/ui/popup/popup.scss';
|
||||
composes: popupWrapper from '~components/ui/popup/popup.scss';
|
||||
|
||||
@include popupBounding(280px);
|
||||
}
|
||||
@ -11,7 +11,7 @@
|
||||
}
|
||||
|
||||
.lockIcon {
|
||||
composes: lock from 'components/ui/icons.scss';
|
||||
composes: lock from '~components/ui/icons.scss';
|
||||
|
||||
font-size: 90px;
|
||||
color: #AAA;
|
||||
|
@ -80,7 +80,7 @@ $formColumnWidth: 416px;
|
||||
}
|
||||
|
||||
.paramEditIcon {
|
||||
composes: pencil from 'components/ui/icons.scss';
|
||||
composes: pencil from '~components/ui/icons.scss';
|
||||
|
||||
color: $white;
|
||||
transition: .4s;
|
||||
|
@ -27,7 +27,7 @@
|
||||
}
|
||||
|
||||
.backIcon {
|
||||
composes: arrowLeft from 'components/ui/icons.scss';
|
||||
composes: arrowLeft from '~components/ui/icons.scss';
|
||||
|
||||
position: relative;
|
||||
}
|
||||
|
@ -55,7 +55,7 @@ $dropdownPadding: 15px;
|
||||
}
|
||||
|
||||
.toggleIcon {
|
||||
composes: selecter from 'components/ui/icons.scss';
|
||||
composes: selecter from '~components/ui/icons.scss';
|
||||
|
||||
position: absolute;
|
||||
right: $dropdownPadding;
|
||||
|
@ -284,7 +284,7 @@
|
||||
|
||||
.mark {
|
||||
composes: markPosition;
|
||||
composes: checkmark from 'components/ui/icons.scss';
|
||||
composes: checkmark from '~components/ui/icons.scss';
|
||||
|
||||
border: 2px #dcd8cd solid;
|
||||
|
||||
|
@ -23,7 +23,7 @@ $headerHeight: 60px;
|
||||
}
|
||||
|
||||
.headerControl {
|
||||
composes: black from 'components/ui/buttons.scss';
|
||||
composes: black from '~components/ui/buttons.scss';
|
||||
|
||||
float: left;
|
||||
overflow: hidden;
|
||||
@ -119,7 +119,7 @@ $bodyTopBottomPadding: 15px;
|
||||
}
|
||||
|
||||
.close {
|
||||
composes: close from 'components/ui/icons.scss';
|
||||
composes: close from '~components/ui/icons.scss';
|
||||
|
||||
position: absolute;
|
||||
right: 5px;
|
||||
|
@ -13,7 +13,7 @@
|
||||
}
|
||||
|
||||
.activeAccountButton {
|
||||
composes: green from 'components/ui/buttons.scss';
|
||||
composes: green from '~components/ui/buttons.scss';
|
||||
}
|
||||
|
||||
.activeAccountExpanded {
|
||||
@ -31,7 +31,7 @@
|
||||
}
|
||||
|
||||
.userIcon {
|
||||
composes: user from 'components/ui/icons.scss';
|
||||
composes: user from '~components/ui/icons.scss';
|
||||
|
||||
position: relative;
|
||||
bottom: 2px;
|
||||
@ -40,7 +40,7 @@
|
||||
}
|
||||
|
||||
.expandIcon {
|
||||
composes: caret from 'components/ui/icons.scss';
|
||||
composes: caret from '~components/ui/icons.scss';
|
||||
|
||||
margin-left: 4px;
|
||||
font-size: 6px;
|
||||
|
@ -52,7 +52,7 @@
|
||||
}
|
||||
|
||||
.checkmark {
|
||||
composes: checkmark from 'components/ui/icons.scss';
|
||||
composes: checkmark from '~components/ui/icons.scss';
|
||||
|
||||
color: lighter($green);
|
||||
font-size: 66px;
|
||||
|
@ -34,17 +34,17 @@ export default {
|
||||
messages: { [string]: string };
|
||||
}> {
|
||||
const promises: Array<Promise<any>> = [
|
||||
import(/* webpackChunkName: "[request]-locale" */`react-intl/locale-data/${locale}.js`),
|
||||
import(/* webpackChunkName: "[request]-locale" */`i18n/${locale}.json`),
|
||||
import(/* webpackChunkName: "locale-[request]" */`react-intl/locale-data/${locale}.js`),
|
||||
import(/* webpackChunkName: "locale-[request]" */`i18n/${locale}.json`),
|
||||
];
|
||||
|
||||
if (needPolyfill) {
|
||||
promises.push(import(/* webpackChunkName: "[request]-intl-polyfill" */ 'intl'));
|
||||
promises.push(import(/* webpackChunkName: "[request]-intl-polyfill" */`intl/locale-data/jsonp/${locale}.js`));
|
||||
promises.push(import(/* webpackChunkName: "intl-polyfill" */'intl'));
|
||||
promises.push(import(/* webpackChunkName: "intl-polyfill-[request]" */`intl/locale-data/jsonp/${locale}.js`));
|
||||
}
|
||||
|
||||
return Promise.all(promises)
|
||||
.then(([localeData, messages]) => {
|
||||
.then(([localeData, {default: messages}]) => {
|
||||
addLocaleData(localeData);
|
||||
|
||||
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);
|
||||
|
||||
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, '.');
|
||||
|
||||
content = JSON.stringify(Object.keys(content).reduce(function(translations, key) {
|
||||
translations[key] = {
|
||||
id: moduleId + '.' + key,
|
||||
defaultMessage: content[key]
|
||||
};
|
||||
content = JSON.stringify(
|
||||
Object.keys(content).reduce(
|
||||
(translations, 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": [],
|
||||
"author": "",
|
||||
"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');
|
||||
|
||||
const path = require('path');
|
||||
|
||||
const webpack = require('webpack');
|
||||
const loaderUtils = require('loader-utils');
|
||||
const chalk = require('chalk');
|
||||
const ExtractTextPlugin = require('extract-text-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 CSPPlugin = require('csp-webpack-plugin');
|
||||
const localeFlags = require('./src/components/i18n/localeFlags').default;
|
||||
|
||||
const SUPPORTED_LANGUAGES = Object.keys(require('./src/i18n/index.json'));
|
||||
const localeFlags = require('./src/components/i18n/localeFlags').default;
|
||||
const rootPath = path.resolve('./src');
|
||||
const outputPath = path.join(__dirname, 'dist');
|
||||
|
||||
const packageJson = require('./package.json');
|
||||
|
||||
let config = {};
|
||||
try {
|
||||
config = require('./config/env.js');
|
||||
} 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') {
|
||||
console.error(err);
|
||||
@ -55,38 +52,11 @@ const isSilent = isCI || process.argv.some((arg) => /quiet/.test(arg));
|
||||
const isCspEnabled = false;
|
||||
|
||||
process.env.NODE_ENV = isProduction ? 'production' : 'development';
|
||||
|
||||
if (isTest) {
|
||||
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 = {
|
||||
cache: true,
|
||||
|
||||
@ -105,24 +75,33 @@ const webpackConfig = {
|
||||
extensions: ['.js', '.jsx', '.json']
|
||||
},
|
||||
|
||||
externals: isTest ? {
|
||||
sinon: 'sinon',
|
||||
// http://airbnb.io/enzyme/docs/guides/webpack.html
|
||||
cheerio: 'window',
|
||||
'react/lib/ExecutionEnvironment': true,
|
||||
'react/lib/ReactContext': true,
|
||||
'react/addons': true
|
||||
} : {},
|
||||
externals: isTest
|
||||
? {
|
||||
sinon: 'sinon',
|
||||
// http://airbnb.io/enzyme/docs/guides/webpack.html
|
||||
cheerio: 'window',
|
||||
'react/lib/ExecutionEnvironment': true,
|
||||
'react/lib/ReactContext': true,
|
||||
'react/addons': true
|
||||
}
|
||||
: {},
|
||||
|
||||
devtool: 'cheap-module-source-map',
|
||||
|
||||
plugins: [
|
||||
new webpack.DefinePlugin({
|
||||
'window.SENTRY_CDN': config.sentryCdn ? JSON.stringify(config.sentryCdn) : undefined,
|
||||
'window.GA_ID': config.ga && config.ga.id ? JSON.stringify(config.ga.id) : undefined,
|
||||
'window.SENTRY_CDN': config.sentryCdn
|
||||
? JSON.stringify(config.sentryCdn)
|
||||
: undefined,
|
||||
'window.GA_ID':
|
||||
config.ga && config.ga.id
|
||||
? JSON.stringify(config.ga.id)
|
||||
: undefined,
|
||||
'process.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 || ''),
|
||||
__DEV__: !isProduction,
|
||||
__TEST__: isTest,
|
||||
@ -139,31 +118,37 @@ const webpackConfig = {
|
||||
minify: {
|
||||
collapseWhitespace: isProduction
|
||||
},
|
||||
isCspEnabled,
|
||||
}),
|
||||
new SitemapPlugin('https://account.ely.by', [
|
||||
'/',
|
||||
'/register',
|
||||
'/resend-activation',
|
||||
'/activation',
|
||||
'/forgot-password',
|
||||
'/rules',
|
||||
], {
|
||||
lastMod: true,
|
||||
changeFreq: 'weekly',
|
||||
isCspEnabled
|
||||
}),
|
||||
new SitemapPlugin(
|
||||
'https://account.ely.by',
|
||||
[
|
||||
'/',
|
||||
'/register',
|
||||
'/resend-activation',
|
||||
'/activation',
|
||||
'/forgot-password',
|
||||
'/rules'
|
||||
],
|
||||
{
|
||||
lastMod: true,
|
||||
changeFreq: 'weekly'
|
||||
}
|
||||
),
|
||||
new webpack.ProvidePlugin({
|
||||
React: 'react'
|
||||
}),
|
||||
// restrict webpack import context, to create chunks only for supported locales
|
||||
// @see services/i18n.js
|
||||
new webpack.ContextReplacementPlugin(
|
||||
/locale-data/, new RegExp(`/(${SUPPORTED_LANGUAGES.join('|')})\\.js`)
|
||||
/locale-data/,
|
||||
new RegExp(`/(${SUPPORTED_LANGUAGES.join('|')})\\.js`)
|
||||
),
|
||||
// @see components/i18n/localeFlags.js
|
||||
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: {
|
||||
@ -174,15 +159,28 @@ const webpackConfig = {
|
||||
'style-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',
|
||||
options: {
|
||||
syntax: 'postcss-scss',
|
||||
ident: 'postcss',
|
||||
plugins: postcss
|
||||
sourceMap: !isProduction,
|
||||
config: { path: __dirname }
|
||||
}
|
||||
}
|
||||
]
|
||||
@ -213,12 +211,6 @@ const webpackConfig = {
|
||||
query: {
|
||||
name: 'assets/fonts/[name].[ext]?[hash]'
|
||||
}
|
||||
|
||||
},
|
||||
{
|
||||
test: /\.json$/,
|
||||
exclude: /(intl|font)\.json/,
|
||||
loader: 'json-loader'
|
||||
},
|
||||
{
|
||||
test: /\.html$/,
|
||||
@ -226,20 +218,25 @@ const webpackConfig = {
|
||||
},
|
||||
{
|
||||
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)$/,
|
||||
loader: 'raw-loader!fontgen-loader'
|
||||
type: 'javascript/auto',
|
||||
use: ['fontgen-loader']
|
||||
}
|
||||
]
|
||||
},
|
||||
|
||||
resolveLoader: {
|
||||
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) {
|
||||
@ -248,7 +245,7 @@ if (isProduction) {
|
||||
// remove style-loader from chain and pass through ExtractTextPlugin
|
||||
loader.use = ExtractTextPlugin.extract({
|
||||
fallbackLoader: loader.use[0], // style-loader
|
||||
loader: loader.use,
|
||||
loader: loader.use
|
||||
});
|
||||
}
|
||||
});
|
||||
@ -264,12 +261,11 @@ if (isProduction) {
|
||||
|
||||
webpackConfig.devtool = 'hidden-source-map';
|
||||
|
||||
const ignoredPlugins = [
|
||||
'flag-icon-css',
|
||||
];
|
||||
const ignoredPlugins = ['flag-icon-css'];
|
||||
|
||||
webpackConfig.entry.vendor = Object.keys(packageJson.dependencies)
|
||||
.filter((module) => !ignoredPlugins.includes(module));
|
||||
webpackConfig.entry.vendor = Object.keys(packageJson.dependencies).filter(
|
||||
(module) => !ignoredPlugins.includes(module)
|
||||
);
|
||||
} else {
|
||||
webpackConfig.plugins.push(
|
||||
new webpack.DllReferencePlugin({
|
||||
@ -280,50 +276,51 @@ if (isProduction) {
|
||||
}
|
||||
|
||||
if (!isProduction && !isTest) {
|
||||
webpackConfig.plugins.push(
|
||||
new webpack.HotModuleReplacementPlugin(),
|
||||
);
|
||||
webpackConfig.plugins.push(new webpack.HotModuleReplacementPlugin());
|
||||
|
||||
if (config.apiHost) {
|
||||
webpackConfig.devServer = {
|
||||
host: 'localhost',
|
||||
port: 8080,
|
||||
proxy: {
|
||||
'/api': {
|
||||
target: config.apiHost,
|
||||
changeOrigin: true, // add host http-header, based on target
|
||||
secure: false // allow self-signed certs
|
||||
}
|
||||
},
|
||||
hot: true,
|
||||
inline: true,
|
||||
historyApiFallback: true
|
||||
};
|
||||
}
|
||||
webpackConfig.devServer = {
|
||||
host: 'localhost',
|
||||
port: 8080,
|
||||
proxy: config.apiHost && {
|
||||
'/api': {
|
||||
target: config.apiHost,
|
||||
changeOrigin: true, // add host http-header, based on target
|
||||
secure: false // allow self-signed certs
|
||||
}
|
||||
},
|
||||
hot: true,
|
||||
inline: true,
|
||||
historyApiFallback: true
|
||||
};
|
||||
}
|
||||
|
||||
if (isCspEnabled) {
|
||||
webpackConfig.plugins.push(new CSPPlugin({
|
||||
'default-src': '\'none\'',
|
||||
'style-src': ['\'self\'', '\'unsafe-inline\''],
|
||||
'script-src': [
|
||||
'\'self\'',
|
||||
'\'nonce-edge-must-die\'',
|
||||
'\'unsafe-inline\'',
|
||||
'https://www.google-analytics.com',
|
||||
'https://recaptcha.net/recaptcha/',
|
||||
'https://www.gstatic.com/recaptcha/',
|
||||
'https://www.gstatic.cn/recaptcha/',
|
||||
],
|
||||
'img-src': ['\'self\'', 'data:', 'www.google-analytics.com'],
|
||||
'font-src': ['\'self\'', 'data:'],
|
||||
'connect-src': ['\'self\'', 'https://sentry.ely.by'].concat(isProduction ? [] : ['ws://localhost:8080']),
|
||||
'frame-src': [
|
||||
'https://www.google.com/recaptcha/',
|
||||
'https://recaptcha.net/recaptcha/',
|
||||
],
|
||||
'report-uri': 'https://sentry.ely.by/api/2/csp-report/?sentry_key=088e7718236a4f91937a81fb319a93f6',
|
||||
}));
|
||||
webpackConfig.plugins.push(
|
||||
new CSPPlugin({
|
||||
'default-src': '\'none\'',
|
||||
'style-src': ['\'self\'', '\'unsafe-inline\''],
|
||||
'script-src': [
|
||||
'\'self\'',
|
||||
'\'nonce-edge-must-die\'',
|
||||
'\'unsafe-inline\'',
|
||||
'https://www.google-analytics.com',
|
||||
'https://recaptcha.net/recaptcha/',
|
||||
'https://www.gstatic.com/recaptcha/',
|
||||
'https://www.gstatic.cn/recaptcha/'
|
||||
],
|
||||
'img-src': ['\'self\'', 'data:', 'www.google-analytics.com'],
|
||||
'font-src': ['\'self\'', 'data:'],
|
||||
'connect-src': ['\'self\'', 'https://sentry.ely.by'].concat(
|
||||
isProduction ? [] : ['ws://localhost:8080']
|
||||
),
|
||||
'frame-src': [
|
||||
'https://www.google.com/recaptcha/',
|
||||
'https://recaptcha.net/recaptcha/'
|
||||
],
|
||||
'report-uri':
|
||||
'https://sentry.ely.by/api/2/csp-report/?sentry_key=088e7718236a4f91937a81fb319a93f6'
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
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;
|
||||
|
@ -1,23 +1,26 @@
|
||||
/* eslint-env node */
|
||||
|
||||
const path = require('path');
|
||||
|
||||
const webpack = require('webpack');
|
||||
|
||||
const vendor = Object.keys(require('./package.json').dependencies);
|
||||
|
||||
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);
|
||||
|
||||
process.env.NODE_ENV = 'development';
|
||||
|
||||
if (isTest) {
|
||||
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 webpackConfig = {
|
||||
mode: 'development',
|
||||
|
||||
entry: {
|
||||
vendor: vendor.concat([
|
||||
'core-js/library',
|
||||
@ -26,12 +29,10 @@ const webpackConfig = {
|
||||
'redux-devtools-log-monitor',
|
||||
'react-transform-hmr',
|
||||
'react-transform-catch-errors',
|
||||
'redbox-react',
|
||||
'react-intl/locale-data/en.js',
|
||||
'react-intl/locale-data/ru.js',
|
||||
'react-intl/locale-data/be.js',
|
||||
'react-intl/locale-data/uk.js'
|
||||
])
|
||||
]).concat(
|
||||
Object.keys(supportedLocales)
|
||||
.map((locale) => `react-intl/locale-data/${locale}.js`)
|
||||
)
|
||||
},
|
||||
|
||||
output: {
|
||||
@ -54,11 +55,7 @@ const webpackConfig = {
|
||||
name: '[name]',
|
||||
path: path.join(outputPath, '[name].json')
|
||||
})
|
||||
].concat(isProduction ? [
|
||||
new webpack.optimize.DedupePlugin(),
|
||||
new webpack.optimize.OccurenceOrderPlugin(true),
|
||||
new webpack.optimize.UglifyJsPlugin()
|
||||
] : [])
|
||||
]
|
||||
};
|
||||
|
||||
module.exports = webpackConfig;
|
||||
|
Loading…
Reference in New Issue
Block a user