Verified Commit ee872c44 authored by FabioWidmer's avatar FabioWidmer
Browse files

Improve SEO

parent ae20fe50
...@@ -6,31 +6,31 @@ const config = require('./webpack.config.js'); ...@@ -6,31 +6,31 @@ const config = require('./webpack.config.js');
const env = process.env.NODE_ENV || 'development'; const env = process.env.NODE_ENV || 'development';
const target = process.env.TARGET || 'web'; const target = process.env.TARGET || 'web';
const isCordova = target === 'cordova' const isCordova = target === 'cordova';
const spinner = ora(env === 'production' ? 'building for production...' : 'building development version...'); const spinner = ora(env === 'production' ? 'building for production...' : 'building development version...');
spinner.start(); spinner.start();
rm(isCordova ? './cordova/www' : './www/', (removeErr) => { rm(isCordova ? './cordova/www' : './www/', (removeErr) => {
if (removeErr) throw removeErr; if(removeErr) throw removeErr;
webpack(config, (err, stats) => { webpack(config, (err, stats) => {
if (err) throw err; if(err) throw err;
spinner.stop(); spinner.stop();
process.stdout.write(`${stats.toString({ process.stdout.write(`${stats.toString({
colors: true, colors: true,
modules: false, modules: false,
children: false, // If you are using ts-loader, setting this to true will make TypeScript errors show up during build. children: false, // If you are using ts-loader, setting this to true will make TypeScript errors show up during build.
chunks: false, chunks: false,
chunkModules: false, chunkModules: false,
})}\n\n`); })}\n\n`);
if (stats.hasErrors()) { if(stats.hasErrors()) {
console.log(chalk.red('Build failed with errors.\n')); console.log(chalk.red('Build failed with errors.\n'));
process.exit(1); process.exit(1);
} }
console.log(chalk.cyan('Build complete.\n')); console.log(chalk.cyan('Build complete.\n'));
}); });
}); });
...@@ -10,212 +10,232 @@ const WorkboxPlugin = require('workbox-webpack-plugin'); ...@@ -10,212 +10,232 @@ const WorkboxPlugin = require('workbox-webpack-plugin');
const path = require('path'); const path = require('path');
function resolvePath(dir) { function resolvePath(dir) {
return path.join(__dirname, '..', dir); return path.join(__dirname, '..', dir);
} }
const env = process.env.NODE_ENV || 'development'; const env = process.env.NODE_ENV || 'development';
const target = process.env.TARGET || 'web'; const target = process.env.TARGET || 'web';
const isCordova = target === 'cordova'; const isCordova = target === 'cordova';
const isElectronWatch = process.env.ELECTRON_WATCH || false; const isElectronWatch = process.env.ELECTRON_WATCH || false;
const hashName = env === 'production' ? '.[hash:8]' : '';
module.exports = { module.exports = {
mode: env, mode: env,
entry: { entry: {
app: './src/js/app.js', app: './src/js/app.js',
}, },
output: { output: {
path: resolvePath(isCordova ? (isElectronWatch ? 'cordova/platforms/electron/www' : 'cordova/www') : 'www'), path: resolvePath(isCordova ? (isElectronWatch ? 'cordova/platforms/electron/www' : 'cordova/www') : 'www'),
filename: 'js/[name].js', filename: `js/[name]${hashName}.js`,
chunkFilename: 'js/[name].js', chunkFilename: `js/[name]${hashName}.js`,
publicPath: '', publicPath: '',
hotUpdateChunkFilename: 'hot/hot-update.js', hotUpdateChunkFilename: 'hot/hot-update.js',
hotUpdateMainFilename: 'hot/hot-update.json', hotUpdateMainFilename: 'hot/hot-update.json',
}, },
resolve: { resolve: {
extensions: ['.js', '.vue', '.json'], extensions: ['.js', '.vue', '.json'],
alias: { alias: {
vue$: 'vue/dist/vue.esm.js', vue$: 'vue/dist/vue.esm.js',
'@': resolvePath('src'), '@': resolvePath('src'),
}, },
}, },
devtool: env === 'production' ? 'source-map' : 'eval', devtool: env === 'production' ? 'source-map' : 'eval',
devServer: { devServer: {
hot: false, //Changed hot: false, //Changed
open: true, open: true,
compress: true, compress: true,
contentBase: '/www/', contentBase: '/www/',
disableHostCheck: true, disableHostCheck: true,
historyApiFallback: true, historyApiFallback: true,
watchOptions: { watchOptions: {
poll: 1000, poll: 1000,
}, },
}, },
optimization: { optimization: {
minimizer: [new TerserPlugin({ minimizer: [
sourceMap: true, new TerserPlugin({
})], sourceMap: true,
}, }),
module: { ],
rules: [ },
{ module: {
test: /\.(mjs|js|jsx)$/, rules: [
use: 'babel-loader', {
include: [ test: /\.(mjs|js|jsx)$/,
resolvePath('src'), use: 'babel-loader',
resolvePath('node_modules/framework7'), include: [
resolvePath('node_modules/framework7-vue'), resolvePath('src'),
resolvePath('node_modules/framework7'),
resolvePath('node_modules/framework7-vue'),
resolvePath('node_modules/template7'),
resolvePath('node_modules/dom7'),
resolvePath('node_modules/ssr-window'),
],
},
resolvePath('node_modules/template7'), {
resolvePath('node_modules/dom7'), test: /\.vue$/,
resolvePath('node_modules/ssr-window'), use: 'vue-loader',
], },
}, {
test: /\.css$/,
use: [
(env === 'development' ? 'style-loader' : {
loader: MiniCssExtractPlugin.loader,
options: {
publicPath: '../',
},
}),
'css-loader',
'postcss-loader',
],
},
{
test: /\.styl(us)?$/,
use: [
(env === 'development' ? 'style-loader' : {
loader: MiniCssExtractPlugin.loader,
options: {
publicPath: '../',
},
}),
'css-loader',
'postcss-loader',
'stylus-loader',
],
},
{
test: /\.less$/,
use: [
(env === 'development' ? 'style-loader' : {
loader: MiniCssExtractPlugin.loader,
options: {
publicPath: '../',
},
}),
'css-loader',
'postcss-loader',
'less-loader',
],
},
{
test: /\.(sa|sc)ss$/,
use: [
(env === 'development' ? 'style-loader' : {
loader: MiniCssExtractPlugin.loader,
options: {
publicPath: '../',
},
}),
'css-loader',
'postcss-loader',
'sass-loader',
],
},
{
test: /\.(png|jpe?g|gif|svg)(\?.*)?$/,
loader: 'url-loader',
options: {
limit: 10000,
name: `images/[name]${hashName}.[ext]`,
},
},
{
test: /\.(mp4|webm|ogg|mp3|wav|flac|aac|m4a)(\?.*)?$/,
loader: 'url-loader',
options: {
limit: 10000,
name: `media/[name]${hashName}.[ext]`,
{ },
test: /\.vue$/, },
use: 'vue-loader', {
}, test: /\.(woff2?|eot|ttf|otf)(\?.*)?$/,
{ loader: 'url-loader',
test: /\.css$/, options: {
use: [ limit: 10000,
(env === 'development' ? 'style-loader' : { name: `fonts/[name]${hashName}.[ext]`,
loader: MiniCssExtractPlugin.loader,
options: {
publicPath: '../'
}
}),
'css-loader',
'postcss-loader',
],
},
{
test: /\.styl(us)?$/,
use: [
(env === 'development' ? 'style-loader' : {
loader: MiniCssExtractPlugin.loader,
options: {
publicPath: '../'
}
}),
'css-loader',
'postcss-loader',
'stylus-loader',
],
},
{
test: /\.less$/,
use: [
(env === 'development' ? 'style-loader' : {
loader: MiniCssExtractPlugin.loader,
options: {
publicPath: '../'
}
}),
'css-loader',
'postcss-loader',
'less-loader',
],
},
{
test: /\.(sa|sc)ss$/,
use: [
(env === 'development' ? 'style-loader' : {
loader: MiniCssExtractPlugin.loader,
options: {
publicPath: '../'
}
}),
'css-loader',
'postcss-loader',
'sass-loader',
],
},
{
test: /\.(png|jpe?g|gif|svg)(\?.*)?$/,
loader: 'url-loader',
options: {
limit: 10000,
name: 'images/[name].[ext]',
}, },
}, },
{ ],
test: /\.(mp4|webm|ogg|mp3|wav|flac|aac|m4a)(\?.*)?$/, },
loader: 'url-loader', plugins: [
options: { new webpack.DefinePlugin({
limit: 10000, 'process.env.NODE_ENV': JSON.stringify(env),
name: 'media/[name].[ext]', 'process.env.TARGET': JSON.stringify(target),
}),
}, new VueLoaderPlugin(),
}, ...(env === 'production' ? [
{ new OptimizeCSSPlugin({
test: /\.(woff2?|eot|ttf|otf)(\?.*)?$/, cssProcessorOptions: {
loader: 'url-loader', safe: true,
options: { map: {inline: false},
limit: 10000, },
name: 'fonts/[name].[ext]', }),
new webpack.optimize.ModuleConcatenationPlugin(),
}, ] : [
}, // Development only plugins
], new webpack.HotModuleReplacementPlugin(),
}, new webpack.NamedModulesPlugin(),
plugins: [ ]),
new webpack.DefinePlugin({ new HtmlWebpackPlugin({
'process.env.NODE_ENV': JSON.stringify(env), filename: './index.html',
'process.env.TARGET': JSON.stringify(target), template: './src/index.html',
}), inject: true,
new VueLoaderPlugin(), minify: env === 'production' ? {
...(env === 'production' ? [ collapseWhitespace: true,
new OptimizeCSSPlugin({ removeComments: true,
cssProcessorOptions: { removeRedundantAttributes: true,
safe: true, removeScriptTypeAttributes: true,
map: { inline: false }, removeStyleLinkTypeAttributes: true,
}, useShortDoctype: true,
}), } : false,
new webpack.optimize.ModuleConcatenationPlugin(), }),
] : [ new MiniCssExtractPlugin({
// Development only plugins filename: `css/[name]${hashName}.css`,
new webpack.HotModuleReplacementPlugin(), }),
new webpack.NamedModulesPlugin(), new CopyWebpackPlugin({
]), patterns: [
new HtmlWebpackPlugin({ {
filename: './index.html', noErrorOnMissing: true,
template: './src/index.html', from: resolvePath('src/static'),
inject: true, to: resolvePath(isCordova ? 'cordova/www/static' : 'www/static'),
minify: env === 'production' ? { },
collapseWhitespace: true, {
removeComments: true, noErrorOnMissing: true,
removeRedundantAttributes: true, from: resolvePath('src/.htaccess'),
removeScriptTypeAttributes: true, to: resolvePath('www'),
removeStyleLinkTypeAttributes: true, },
useShortDoctype: true {
} : false, noErrorOnMissing: true,
}), from: resolvePath('src/manifest.json'),
new MiniCssExtractPlugin({ to: resolvePath('www/manifest.json'),
filename: 'css/[name].css', },
}), {
new CopyWebpackPlugin({ noErrorOnMissing: true,
patterns: [ from: resolvePath('src/robots.txt'),
{ to: resolvePath('www/robots.txt'),
noErrorOnMissing: true, },
from: resolvePath('src/static'), {
to: resolvePath(isCordova ? 'cordova/www/static' : 'www/static'), noErrorOnMissing: true,
}, from: resolvePath('src/sitemap.xml'),
{ to: resolvePath('www/sitemap.xml'),
noErrorOnMissing: true, },
from: resolvePath('src/manifest.json'), {
to: resolvePath('www/manifest.json'), noErrorOnMissing: true,
}, from: resolvePath('src/assetlinks.json'),
], to: resolvePath('www/.well-known'),
}), },
...(!isCordova ? [ ],
new WorkboxPlugin.InjectManifest({ }),
swSrc: resolvePath('src/service-worker.js'), ...(!isCordova ? [
}) new WorkboxPlugin.InjectManifest({
] : []), swSrc: resolvePath('src/service-worker.js'),
}),
], ] : []),
],
}; };
...@@ -5,7 +5,7 @@ ...@@ -5,7 +5,7 @@
<author email="info@ablota.com" href="https://ablota.com">Ablota (StarApps GmbH)</author> <author email="info@ablota.com" href="https://ablota.com">Ablota (StarApps GmbH)</author>
<content src="index.html"/> <content src="index.html"/>
<access origin="https://store.ablota.com"/> <access origin="https://api.store.ablota.com"/>
<allow-intent href="http://*/*"/> <allow-intent href="http://*/*"/>
<allow-intent href="https://*/*"/> <allow-intent href="https://*/*"/>
<allow-intent href="mailto:*"/> <allow-intent href="mailto:*"/>
......
...@@ -11,9 +11,9 @@ ...@@ -11,9 +11,9 @@
"dev": true "dev": true
}, },
"@ablota/store-cordova-plugin": { "@ablota/store-cordova-plugin": {
"version": "1.0.0", "version": "1.0.1",
"resolved": "https://gitlab.starapps-network.com/api/v4/projects/34/packages/npm/@ablota/store-cordova-plugin/-/@ablota/store-cordova-plugin-1.0.0.tgz", "resolved": "https://gitlab.starapps-network.com/api/v4/projects/34/packages/npm/@ablota/store-cordova-plugin/-/@ablota/store-cordova-plugin-1.0.1.tgz",
"integrity": "sha1-A9Y1N/0ABxuSYo1g3cTu0P1oTsw=", "integrity": "sha1-U9REcXaMdp5+/Q56mHtMpV3ollk=",
"dev": true "dev": true
}, },
"@develar/schema-utils": { "@develar/schema-utils": {
......
...@@ -27,7 +27,7 @@ ...@@ -27,7 +27,7 @@
] ]
}, },
"devDependencies": { "devDependencies": {
"@ablota/store-cordova-plugin": "^1.0.0", "@ablota/store-cordova-plugin": "^1.0.1",
"cordova-android": "^9.0.0", "cordova-android": "^9.0.0",
"cordova-clipboard": "^1.3.0", "cordova-clipboard": "^1.3.0",
"cordova-electron": "^2.0.0", "cordova-electron": "^2.0.0",
......
<IfModule mod_deflate.c>
AddOutputFilterByType DEFLATE "application/atom+xml" "application/javascript" "application/json" "application/ld+json" "application/manifest+json" "application/rdf+xml" "application/rss+xml" "application/schema+json" "application/vnd.geo+json" "application/vnd.ms-fontobject" "application/x-font-ttf" "application/x-javascript" "application/x-web-app-manifest+json" "application/xhtml+xml" "application/xml" "font/eot" "font/opentype" "image/bmp" "image/svg+xml" "image/vnd.microsoft.icon" "image/x-icon" "text/cache-manifest" "text/css" "text/html" "text/javascript" "text/plain" "text/vcard" "text/vnd.rim.location.xloc" "text/vtt" "text/x-component" "text/x-cross-domain-policy" "text/xml"
</IfModule>
<IfModule mod_negotiation.c>
Options -MultiViews -Indexes
</IfModule>
<IfModule mod_headers.c>
<FilesMatch "\.(css|js|ico|gif|jpeg|jpg|png|svg|eot|ttf|woff|woff2)$">
Header set Cache-Control "max-age=31536000, public"
</FilesMatch>
</IfModule>
<IfModule mod_rewrite.c>
RewriteCond %{HTTP_HOST} =ablota.store [NC]
RewriteRule ^(.*)$ https://store.ablota.com/$1 [R=301,NE,L]
RewriteCond %{HTTP_HOST} ^www\.(.*)$ [NC]
RewriteRule ^(.*)$ https://%1/$1 [R=301,NE,L]
RewriteCond %{HTTPS} !on
RewriteRule ^(.*)$ https://%{HTTP_HOST}%{REQUEST_URI} [R=301,NE,L]
ErrorDocument 404 https://%{HTTP_HOST}
</IfModule>
[
{
"relation": [
"delegate_permission/common.handle_all_urls"
],
"target": {
"namespace": "android_app",
"package_name": "com.ablota.store",
"sha256_cert_fingerprints": [
"5E:A5:AE:2F:48:1E:00:E1:B0:A3:88:CA:4E:CC:0B:84:B3:89:1A:6C:0B:32:F5:9C:59:AA:B2:A0:71:A2:51:46"
]
}
}
]
...@@ -24,7 +24,7 @@ ...@@ -24,7 +24,7 @@
return { return {
url: 'https://store.ablota.com/', url: 'https://store.ablota.com/',
server: { server: {
url: 'http://localhost:8000/' url: 'https://api.store.ablota.com/'
}, },
}; };
}, },
......
...@@ -14,7 +14,7 @@ ...@@ -14,7 +14,7 @@
<div class="timeline-item-inner"> <div class="timeline-item-inner">
<div class="timeline-item-title">{{ $t('words.download') }}</div> <div class="timeline-item-title">{{ $t('words.download') }}</div>
<div class="timeline-item-text">{{ $t('popups.downloadApp.steps.download.description') }}</div> <div class="timeline-item-text">{{ $t('popups.downloadApp.steps.download.description') }}</div>
<f7-button href="https://ablota.com/repo/Ablota_Store.apk" :text="$t('words.download')" fill raised></f7-button> <f7-button href="https://ablota.com/repo/Ablota_Store.apk" :text="$t('words.download')" fill raised external></f7-button>
</div> </div>
</div> </div>
</div> </div>
...@@ -45,7 +45,7 @@ ...@@ -45,7 +45,7 @@
<div class="timeline-item-inner"> <div class="timeline-item-inner">
<div class="timeline-item-title">{{ $t('words.done') }}</div> <div class="timeline-item-title">{{ $t('words.done') }}</div>
<div class="timeline-item-text">{{ $t('popups.downloadApp.steps.done.description') }}</div> <div class="timeline-item-text">{{ $t('popups.downloadApp.steps.done.description') }}</div>
<f7-button href="https://store.ablota.com" :text="$t('words.launch')" fill raised></f7-button> <f7-button href="https://store.ablota.com" :text="$t('words.launch')" fill raised external></f7-button>
</div> </div>
</div> </div>
</div> </div>
......
<!DOCTYPE html> <!DOCTYPE html>
<html> <html lang="en">
<head> <head>