mirror of
https://github.com/elyby/accounts-frontend.git
synced 2024-11-08 17:12:25 +05:30
#56: switch to self-hosted fonts. Improve css urls resolving. Update outdated dependencies
This commit is contained in:
parent
d36e771c4f
commit
fc84fb49c6
@ -51,9 +51,8 @@
|
||||
"bundle-loader": "^0.5.4",
|
||||
"chai": "^3.0.0",
|
||||
"css-loader": "^0.23.0",
|
||||
"cssnano": "^3.4.0",
|
||||
"enzyme": "^2.2.0",
|
||||
"eslint": "^2.11.0",
|
||||
"eslint": "^3.1.1",
|
||||
"eslint-plugin-react": "^5.0.0",
|
||||
"exports-loader": "^0.6.3",
|
||||
"extract-text-webpack-plugin": "^1.0.0",
|
||||
@ -71,11 +70,14 @@
|
||||
"karma-sinon": "^1.0.4",
|
||||
"karma-sourcemap-loader": "*",
|
||||
"karma-webpack": "^1.5.1",
|
||||
"loader-utils": "^0.2.15",
|
||||
"mocha": "^2.2.5",
|
||||
"node-sass": "^3.4.2",
|
||||
"phantomjs-prebuilt": "^2.0.0",
|
||||
"postcss-import": "^8.1.2",
|
||||
"postcss-loader": "^0.9.0",
|
||||
"postcss-url": "^5.1.1",
|
||||
"postcss-scss": "^0.1.8",
|
||||
"postcss-url": "SleepWalker/postcss-url#switch-to-async-api",
|
||||
"raw-loader": "^0.5.1",
|
||||
"react-addons-test-utils": "^15.0.2",
|
||||
"redux-devtools": "^3.3.1",
|
||||
|
@ -84,25 +84,25 @@
|
||||
.langEn {
|
||||
composes: langIco;
|
||||
|
||||
background-image: url('icons/flag_en.svg');
|
||||
background-image: url('~icons/flag_en.svg');
|
||||
}
|
||||
|
||||
.langRu {
|
||||
composes: langIco;
|
||||
|
||||
background-image: url('icons/flag_ru.svg');
|
||||
background-image: url('~icons/flag_ru.svg');
|
||||
}
|
||||
|
||||
.langBe {
|
||||
composes: langIco;
|
||||
|
||||
background-image: url('icons/flag_be.svg');
|
||||
background-image: url('~icons/flag_be.svg');
|
||||
}
|
||||
|
||||
.langUk {
|
||||
composes: langIco;
|
||||
|
||||
background-image: url('icons/flag_uk.svg');
|
||||
background-image: url('~icons/flag_uk.svg');
|
||||
}
|
||||
|
||||
.trigger {
|
||||
|
@ -1,4 +1,3 @@
|
||||
// TODO: should we host fonts from our side?
|
||||
$font-family-title: 'Roboto Condensed', Arial, sans-serif;
|
||||
$font-family-base: 'Roboto', Arial, sans-serif;
|
||||
|
||||
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
BIN
src/fonts/roboto/roboto-v15-cyrillic_latin-500.ttf
Normal file
BIN
src/fonts/roboto/roboto-v15-cyrillic_latin-500.ttf
Normal file
Binary file not shown.
BIN
src/fonts/roboto/roboto-v15-cyrillic_latin-500.woff
Normal file
BIN
src/fonts/roboto/roboto-v15-cyrillic_latin-500.woff
Normal file
Binary file not shown.
BIN
src/fonts/roboto/roboto-v15-cyrillic_latin-500.woff2
Normal file
BIN
src/fonts/roboto/roboto-v15-cyrillic_latin-500.woff2
Normal file
Binary file not shown.
BIN
src/fonts/roboto/roboto-v15-cyrillic_latin-regular.ttf
Normal file
BIN
src/fonts/roboto/roboto-v15-cyrillic_latin-regular.ttf
Normal file
Binary file not shown.
BIN
src/fonts/roboto/roboto-v15-cyrillic_latin-regular.woff
Normal file
BIN
src/fonts/roboto/roboto-v15-cyrillic_latin-regular.woff
Normal file
Binary file not shown.
BIN
src/fonts/roboto/roboto-v15-cyrillic_latin-regular.woff2
Normal file
BIN
src/fonts/roboto/roboto-v15-cyrillic_latin-regular.woff2
Normal file
Binary file not shown.
@ -16,8 +16,6 @@
|
||||
|
||||
<%= require('first-render').default %>
|
||||
|
||||
<link href="//fonts.googleapis.com/css?family=Roboto:400,500&subset=latin,cyrillic" rel="stylesheet" type="text/css">
|
||||
<link href="//fonts.googleapis.com/css?family=Roboto+Condensed&subset=latin,cyrillic" rel="stylesheet" type="text/css">
|
||||
<% for (var css in htmlWebpackPlugin.files.css) { %>
|
||||
<link href="<%= htmlWebpackPlugin.files.css[css] %>" rel="stylesheet">
|
||||
<% } %>
|
||||
|
@ -50,3 +50,33 @@ label,
|
||||
a {
|
||||
-webkit-tap-highlight-color: rgba(0,0,0,0);
|
||||
}
|
||||
|
||||
// Declare fonts here, to be sure that want be imported more than once
|
||||
// @see https://github.com/majodev/google-webfonts-helper to download some other fonts
|
||||
@font-face {
|
||||
font-family: 'Roboto Condensed';
|
||||
font-style: normal;
|
||||
font-weight: 400;
|
||||
src: local('Roboto Condensed'), local('RobotoCondensed-Regular'),
|
||||
url('~fonts/roboto-condensed/roboto-condensed-v13-cyrillic_latin-regular.woff2') format('woff2'), /* Super Modern Browsers */
|
||||
url('~fonts/roboto-condensed/roboto-condensed-v13-cyrillic_latin-regular.woff') format('woff'), /* Modern Browsers */
|
||||
url('~fonts/roboto-condensed/roboto-condensed-v13-cyrillic_latin-regular.ttf') format('truetype'); /* Safari, Android, iOS */
|
||||
}
|
||||
@font-face {
|
||||
font-family: 'Roboto';
|
||||
font-style: normal;
|
||||
font-weight: 400;
|
||||
src: local('Roboto'), local('Roboto-Regular'),
|
||||
url('~fonts/roboto/roboto-v15-cyrillic_latin-regular.woff2') format('woff2'), /* Super Modern Browsers */
|
||||
url('~fonts/roboto/roboto-v15-cyrillic_latin-regular.woff') format('woff'), /* Modern Browsers */
|
||||
url('~fonts/roboto/roboto-v15-cyrillic_latin-regular.ttf') format('truetype'); /* Safari, Android, iOS */
|
||||
}
|
||||
@font-face {
|
||||
font-family: 'Roboto';
|
||||
font-style: normal;
|
||||
font-weight: 500;
|
||||
src: local('Roboto Medium'), local('Roboto-Medium'),
|
||||
url('~fonts/roboto/roboto-v15-cyrillic_latin-500.woff2') format('woff2'), /* Super Modern Browsers */
|
||||
url('~fonts/roboto/roboto-v15-cyrillic_latin-500.woff') format('woff'), /* Modern Browsers */
|
||||
url('~fonts/roboto/roboto-v15-cyrillic_latin-500.ttf') format('truetype'); /* Safari, Android, iOS */
|
||||
}
|
||||
|
@ -3,14 +3,17 @@
|
||||
var path = require('path');
|
||||
|
||||
var webpack = require('webpack');
|
||||
var loaderUtils = require('loader-utils');
|
||||
var ExtractTextPlugin = require('extract-text-webpack-plugin');
|
||||
var HtmlWebpackPlugin = require('html-webpack-plugin');
|
||||
var cssnano = require('cssnano');
|
||||
var cssUrl = require("postcss-url");
|
||||
var cssUrl = require('./webpack/cssUrl');
|
||||
var cssImport = require('postcss-import');
|
||||
var iconfontImporter = require('./webpack/node-sass-iconfont-importer');
|
||||
|
||||
var vendor = Object.keys(require('./package.json').dependencies);
|
||||
|
||||
const rootPath = path.resolve('./src');
|
||||
|
||||
/**
|
||||
* TODO: https://babeljs.io/docs/plugins/
|
||||
* TODO: отдельные конфиги для env (аля https://github.com/davezuko/react-redux-starter-kit)
|
||||
@ -24,15 +27,11 @@ var vendor = Object.keys(require('./package.json').dependencies);
|
||||
* https://github.com/davezuko/react-redux-starter-kit
|
||||
*/
|
||||
|
||||
var isProduction = process.argv.some(function(arg) {
|
||||
return arg === '-p';
|
||||
});
|
||||
const isProduction = process.argv.some((arg) => arg === '-p');
|
||||
|
||||
var isTest = process.argv.some(function(arg) {
|
||||
return arg.indexOf('karma') !== -1;
|
||||
});
|
||||
const isTest = process.argv.some((arg) => arg.indexOf('karma') !== -1);
|
||||
|
||||
var isDockerized = !!process.env.DOCKERIZED;
|
||||
const isDockerized = !!process.env.DOCKERIZED;
|
||||
|
||||
process.env.NODE_ENV = isProduction ? 'production' : 'development';
|
||||
if (isTest) {
|
||||
@ -40,8 +39,8 @@ if (isTest) {
|
||||
}
|
||||
|
||||
const CSS_CLASS_TEMPLATE = isProduction ? '[hash:base64:5]' : '[path][name]-[local]';
|
||||
var config;
|
||||
|
||||
var config;
|
||||
try {
|
||||
config = require('./config/dev.json');
|
||||
} catch (err) {
|
||||
@ -49,7 +48,29 @@ try {
|
||||
throw err;
|
||||
}
|
||||
|
||||
var rootPath = path.resolve('./src');
|
||||
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
|
||||
}
|
||||
};
|
||||
|
||||
var webpackConfig = {
|
||||
entry: {
|
||||
@ -70,7 +91,7 @@ var webpackConfig = {
|
||||
|
||||
externals: isTest ? {
|
||||
// http://airbnb.io/enzyme/docs/guides/webpack.html
|
||||
'cheerio': 'window',
|
||||
cheerio: 'window',
|
||||
'react/lib/ExecutionEnvironment': true,
|
||||
'react/lib/ReactContext': true,
|
||||
'react/addons': true
|
||||
@ -130,7 +151,7 @@ var webpackConfig = {
|
||||
{
|
||||
test: /\.scss$/,
|
||||
extractInProduction: true,
|
||||
loader: 'style!css?modules&importLoaders=2&localIdentName=' + CSS_CLASS_TEMPLATE + '!postcss!sass'
|
||||
loader: 'style!css?' + JSON.stringify(cssLoaderQuery) + '!sass!postcss?syntax=postcss-scss'
|
||||
},
|
||||
{
|
||||
test: /\.jsx?$/,
|
||||
@ -139,7 +160,19 @@ var webpackConfig = {
|
||||
},
|
||||
{
|
||||
test: /\.(png|gif|jpg|svg)$/,
|
||||
loader: 'url?limit=1000&name=assets/[name].[ext]?[hash]'
|
||||
loader: 'url',
|
||||
query: {
|
||||
limit: 1000,
|
||||
name: 'assets/[name].[ext]?[hash]'
|
||||
}
|
||||
},
|
||||
{
|
||||
test: /\.(woff|woff2|eot|ttf)$/, // NOTE: svg is loaded by another loader for now
|
||||
loader: 'file',
|
||||
query: {
|
||||
name: 'assets/fonts/[name].[ext]?[hash]'
|
||||
}
|
||||
|
||||
},
|
||||
{
|
||||
test: /\.json$/,
|
||||
@ -163,7 +196,7 @@ var webpackConfig = {
|
||||
|
||||
resolveLoader: {
|
||||
alias: {
|
||||
'intl': path.resolve('./webpack/intl-loader')
|
||||
intl: path.resolve('./webpack/intl-loader')
|
||||
}
|
||||
},
|
||||
|
||||
@ -173,41 +206,36 @@ var webpackConfig = {
|
||||
})
|
||||
},
|
||||
|
||||
postcss: [
|
||||
cssUrl({
|
||||
url: function(url, decl, from, dirname, to, options, result) {
|
||||
// scss не правильно резолвит относительные урлы.
|
||||
// добавляем к урлам остаток пути, что бы они были относительно root
|
||||
//
|
||||
// Например:
|
||||
// file: components/ui/foo.scss
|
||||
// ./images/foo.png -> components/ui/images/foo.png
|
||||
postcss() {
|
||||
// TODO: иконочные шрифты эмитятся > 1 раза
|
||||
return [
|
||||
cssImport({
|
||||
path: rootPath,
|
||||
addDependencyTo: webpack,
|
||||
|
||||
if (url.indexOf('./') === 0) {
|
||||
var relativeToRoot = dirname.split(rootPath + '/')[1];
|
||||
resolve: ((defaultResolve) =>
|
||||
(url, basedir, importOptions) =>
|
||||
defaultResolve(loaderUtils.urlToRequest(url), basedir, importOptions)
|
||||
)(require('postcss-import/lib/resolve-id')),
|
||||
|
||||
return path.join(relativeToRoot, url);
|
||||
}
|
||||
load: ((defaultLoad) =>
|
||||
(filename, importOptions) => {
|
||||
if (/\.font.(js|json)$/.test(filename)) {
|
||||
return new Promise((resolve, reject) =>
|
||||
this.loadModule(filename, (err, source) =>
|
||||
err ? reject(err) : resolve(this.exec(source))
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
return url;
|
||||
}
|
||||
}),
|
||||
cssnano({
|
||||
// sourcemap: !isProduction,
|
||||
autoprefixer: {
|
||||
add: true,
|
||||
remove: true,
|
||||
browsers: ['last 2 versions']
|
||||
},
|
||||
safe: true,
|
||||
// отключаем минификацию цветов, что бы она не ломала такие выражения:
|
||||
// composes: black from './buttons.scss';
|
||||
colormin: false,
|
||||
discardComments: {
|
||||
removeAll: true
|
||||
}
|
||||
})
|
||||
]
|
||||
return defaultLoad(filename, importOptions);
|
||||
}
|
||||
)(require('postcss-import/lib/load-content'))
|
||||
}),
|
||||
|
||||
cssUrl(this)
|
||||
];
|
||||
}
|
||||
};
|
||||
|
||||
if (isDockerized) {
|
||||
@ -220,7 +248,7 @@ if (isDockerized) {
|
||||
if (isProduction) {
|
||||
webpackConfig.module.loaders.forEach((loader) => {
|
||||
if (loader.extractInProduction) {
|
||||
var parts = loader.loader.split('!');
|
||||
const parts = loader.loader.split('!');
|
||||
loader.loader = ExtractTextPlugin.extract(
|
||||
parts[0],
|
||||
parts.slice(1)
|
||||
|
36
webpack/cssUrl.js
Normal file
36
webpack/cssUrl.js
Normal file
@ -0,0 +1,36 @@
|
||||
// при использовании 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}
|
||||
`) + urlPostfix(url)
|
||||
)
|
||||
) : resolve(url)
|
||||
)
|
||||
});
|
||||
};
|
Loading…
Reference in New Issue
Block a user