2018-06-25 18:29:57 +02:00
|
|
|
|
'use strict'
|
|
|
|
|
const path = require('path')
|
2018-08-05 22:05:56 +02:00
|
|
|
|
const svg2png = require('svg2png')
|
|
|
|
|
const webpack = require('webpack')
|
2018-06-25 18:29:57 +02:00
|
|
|
|
|
2018-08-05 22:05:56 +02:00
|
|
|
|
const AppManifestWebpackPlugin = require('app-manifest-webpack-plugin');
|
|
|
|
|
const CopyWebpackPlugin = require('copy-webpack-plugin')
|
|
|
|
|
const HtmlWebpackPlugin = require('html-webpack-plugin')
|
|
|
|
|
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
|
|
|
|
|
const OptimizeCSSAssetsPlugin = require("optimize-css-assets-webpack-plugin");
|
2018-10-25 16:50:38 +02:00
|
|
|
|
const ServiceWorkerWebpackPlugin = require("serviceworker-webpack-plugin");
|
2018-08-05 22:05:56 +02:00
|
|
|
|
const UglifyJsPlugin = require('uglifyjs-webpack-plugin')
|
|
|
|
|
const VueLoaderPlugin = require('vue-loader/lib/plugin')
|
2018-06-25 18:29:57 +02:00
|
|
|
|
|
2018-08-05 22:05:56 +02:00
|
|
|
|
const utils = require('./utils')
|
|
|
|
|
const config = require('../config')
|
2018-06-25 18:29:57 +02:00
|
|
|
|
|
|
|
|
|
module.exports = {
|
2018-08-05 22:05:56 +02:00
|
|
|
|
context: path.resolve(__dirname, '../'),
|
|
|
|
|
entry: {
|
2018-08-13 19:56:43 +02:00
|
|
|
|
app: './src/main.js',
|
2018-08-05 22:05:56 +02:00
|
|
|
|
},
|
|
|
|
|
output: {
|
|
|
|
|
path: config.build.assetsRoot,
|
|
|
|
|
filename: utils.assetsPath('js/[name].js'),
|
|
|
|
|
chunkFilename: utils.assetsPath('js/[name].js'),
|
|
|
|
|
publicPath: config.build.assetsPublicPath,
|
|
|
|
|
},
|
|
|
|
|
optimization: {
|
|
|
|
|
minimizer: [
|
|
|
|
|
new UglifyJsPlugin({
|
|
|
|
|
cache: true,
|
|
|
|
|
parallel: true
|
|
|
|
|
}),
|
|
|
|
|
new OptimizeCSSAssetsPlugin({})
|
|
|
|
|
],
|
|
|
|
|
splitChunks: {
|
2018-08-31 16:21:54 +02:00
|
|
|
|
// Required for webpack to respect the vendor chunk. See
|
|
|
|
|
// https://medium.com/dailyjs/webpack-4-splitchunks-plugin-d9fbbe091fd0
|
|
|
|
|
// for more details.
|
2018-08-05 22:05:56 +02:00
|
|
|
|
chunks: 'initial',
|
|
|
|
|
cacheGroups: {
|
|
|
|
|
vendors: {
|
|
|
|
|
test: /[\\/]node_modules[\\/]|[\\/]css\/vendor[\\/]/,
|
|
|
|
|
},
|
|
|
|
|
},
|
|
|
|
|
},
|
|
|
|
|
},
|
|
|
|
|
resolve: {
|
|
|
|
|
alias: {
|
|
|
|
|
'@': utils.resolve('src'),
|
2018-08-14 15:33:23 +02:00
|
|
|
|
},
|
|
|
|
|
extensions: ['.js', '.vue', '.json'],
|
|
|
|
|
// Load mock_gpx.json from tests first, tests/default then
|
|
|
|
|
modules: ['tests/', 'tests/default', 'node_modules'],
|
2018-08-05 22:05:56 +02:00
|
|
|
|
},
|
|
|
|
|
stats: {
|
|
|
|
|
children: false,
|
|
|
|
|
},
|
|
|
|
|
module: {
|
|
|
|
|
rules: [
|
|
|
|
|
{
|
|
|
|
|
test: /\.(js|vue)$/,
|
|
|
|
|
loader: 'eslint-loader',
|
|
|
|
|
enforce: 'pre',
|
|
|
|
|
include: [utils.resolve('src')],
|
|
|
|
|
options: {
|
|
|
|
|
formatter: require('eslint-friendly-formatter'),
|
|
|
|
|
emitWarning: true,
|
|
|
|
|
},
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
test: /\.vue$/,
|
|
|
|
|
loader: 'vue-loader',
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
test: /\.js$/,
|
|
|
|
|
loader: 'babel-loader',
|
|
|
|
|
exclude: file => (
|
|
|
|
|
/node_modules/.test(file) &&
|
|
|
|
|
!/\.vue\.js/.test(file)
|
|
|
|
|
),
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
test: /\.css$/,
|
|
|
|
|
use: [
|
|
|
|
|
process.env.NODE_ENV !== 'production'
|
|
|
|
|
? 'vue-style-loader'
|
|
|
|
|
: MiniCssExtractPlugin.loader,
|
|
|
|
|
{
|
|
|
|
|
loader: 'css-loader',
|
2018-08-31 16:21:54 +02:00
|
|
|
|
// PostCSS is run before, see
|
|
|
|
|
// https://github.com/webpack-contrib/css-loader#importloaders
|
2018-08-05 22:05:56 +02:00
|
|
|
|
options: { importLoaders: 1 },
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
loader: 'postcss-loader',
|
|
|
|
|
options: {
|
2018-08-31 16:21:54 +02:00
|
|
|
|
plugins: () => [require("postcss-preset-env")()],
|
2018-08-05 22:05:56 +02:00
|
|
|
|
},
|
|
|
|
|
},
|
|
|
|
|
],
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
test: /\.styl(us)?/,
|
|
|
|
|
use: [
|
|
|
|
|
process.env.NODE_ENV !== 'production'
|
|
|
|
|
? 'vue-style-loader'
|
|
|
|
|
: MiniCssExtractPlugin.loader,
|
|
|
|
|
{
|
|
|
|
|
loader: 'css-loader',
|
|
|
|
|
options: { importLoaders: 1 },
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
loader: 'postcss-loader',
|
|
|
|
|
options: {
|
|
|
|
|
plugins: () => [require("autoprefixer")()],
|
|
|
|
|
},
|
|
|
|
|
},
|
|
|
|
|
'stylus-loader',
|
|
|
|
|
],
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
test: /\.(jpe?g|png|gif)$/,
|
|
|
|
|
use: [
|
|
|
|
|
{
|
|
|
|
|
loader: 'url-loader',
|
|
|
|
|
options: {
|
|
|
|
|
name: utils.assetsPath('images/[name].[hash:4].[ext]'),
|
|
|
|
|
// Images larger than 10 KB won’t be inlined
|
|
|
|
|
limit: 10 * 1024,
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
loader: 'image-webpack-loader',
|
|
|
|
|
options: {
|
|
|
|
|
disable: process.env.NODE_ENV !== 'production',
|
|
|
|
|
},
|
|
|
|
|
},
|
|
|
|
|
],
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
test: /\.svg$/,
|
|
|
|
|
use: [
|
|
|
|
|
{
|
|
|
|
|
loader: "svg-url-loader",
|
|
|
|
|
options: {
|
|
|
|
|
name: utils.assetsPath('images/[name].[hash:4].[ext]'),
|
|
|
|
|
// Images larger than 10 KB won’t be inlined
|
|
|
|
|
limit: 10 * 1024,
|
|
|
|
|
noquotes: true,
|
|
|
|
|
},
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
loader: 'image-webpack-loader',
|
|
|
|
|
options: {
|
|
|
|
|
disable: process.env.NODE_ENV !== 'production',
|
|
|
|
|
},
|
|
|
|
|
},
|
|
|
|
|
],
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
test: /\.(mp4|webm|ogg|mp3|wav|flac|aac)$/,
|
|
|
|
|
loader: 'url-loader',
|
|
|
|
|
options: {
|
|
|
|
|
limit: 10 * 1024,
|
|
|
|
|
name: utils.assetsPath('media/[name].[hash:4].[ext]'),
|
|
|
|
|
},
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
test: /\.(woff2?|eot|ttf|otf)$/,
|
|
|
|
|
loader: 'url-loader',
|
|
|
|
|
options: {
|
|
|
|
|
limit: 10 * 1024,
|
|
|
|
|
name: utils.assetsPath('fonts/[name].[hash:4].[ext]'),
|
|
|
|
|
},
|
|
|
|
|
},
|
|
|
|
|
],
|
|
|
|
|
},
|
|
|
|
|
node: {
|
|
|
|
|
// prevent webpack from injecting useless setImmediate polyfill because Vue
|
|
|
|
|
// source contains it (although only uses it if it's native).
|
|
|
|
|
setImmediate: false,
|
|
|
|
|
// prevent webpack from injecting mocks to Node native modules
|
|
|
|
|
// that does not make sense for the client
|
|
|
|
|
dgram: 'empty',
|
|
|
|
|
fs: 'empty',
|
|
|
|
|
net: 'empty',
|
|
|
|
|
tls: 'empty',
|
|
|
|
|
child_process: 'empty',
|
|
|
|
|
},
|
|
|
|
|
plugins: [
|
2018-10-25 16:50:38 +02:00
|
|
|
|
new ServiceWorkerWebpackPlugin({
|
|
|
|
|
entry: path.join(__dirname, '../src/sw.js'),
|
|
|
|
|
}),
|
2018-08-05 22:05:56 +02:00
|
|
|
|
new VueLoaderPlugin(),
|
|
|
|
|
new MiniCssExtractPlugin({
|
|
|
|
|
filename: utils.assetsPath('css/[name].[contenthash:4].css'),
|
|
|
|
|
chunkFilename: utils.assetsPath('css/[name].[contenthash:4].css'),
|
|
|
|
|
}),
|
|
|
|
|
// https://github.com/ampedandwired/html-webpack-plugin
|
|
|
|
|
new HtmlWebpackPlugin({
|
|
|
|
|
filename: 'index.html',
|
|
|
|
|
template: 'index.html',
|
|
|
|
|
ogURL: config.build.ogURL,
|
|
|
|
|
ogImage: config.build.ogImage,
|
|
|
|
|
inject: true,
|
|
|
|
|
minify: (
|
|
|
|
|
process.env.NODE_ENV === 'production'
|
|
|
|
|
? {
|
|
|
|
|
collapseBooleanAttributes: true,
|
|
|
|
|
collapseWhitespace: true,
|
|
|
|
|
html5: true,
|
|
|
|
|
removeAttributeQuotes: true,
|
|
|
|
|
removeComments: true,
|
|
|
|
|
}
|
|
|
|
|
: {}
|
|
|
|
|
),
|
|
|
|
|
}),
|
|
|
|
|
new AppManifestWebpackPlugin({
|
|
|
|
|
logo: path.resolve(__dirname, '../src/assets/logo.svg'),
|
2018-08-22 14:54:21 +02:00
|
|
|
|
prefix: '/',
|
2018-08-05 22:05:56 +02:00
|
|
|
|
output: '/static/icons-[hash:8]/',
|
|
|
|
|
inject: true,
|
|
|
|
|
persistentCache: true,
|
|
|
|
|
config: {
|
|
|
|
|
appName: 'Cyclassist',
|
|
|
|
|
appDescription: "Track and share issues (work, interruption in routes, parked cars) on bike lanes in realtime.",
|
|
|
|
|
developerName: 'Phyks (Lucas Verney)',
|
|
|
|
|
developerURL: 'https://phyks.me',
|
|
|
|
|
}
|
|
|
|
|
}),
|
|
|
|
|
// copy custom static assets
|
|
|
|
|
new CopyWebpackPlugin([
|
|
|
|
|
{
|
|
|
|
|
from: path.resolve(__dirname, '../static'),
|
|
|
|
|
to: config.build.assetsSubDirectory,
|
|
|
|
|
ignore: ['.*']
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
from: path.resolve(__dirname, '../src/assets/logo.svg'),
|
|
|
|
|
to: path.join(config.build.assetsSubDirectory, 'ogIcon.png'),
|
|
|
|
|
transform (content, path) {
|
|
|
|
|
return Promise.resolve(svg2png(content, { width: 400, height: 400 }));
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
from: path.resolve(__dirname, '../humans.txt'),
|
|
|
|
|
to: config.build.assetsRoot,
|
|
|
|
|
ignore: ['.*']
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
from: path.resolve(__dirname, '../robots.txt'),
|
|
|
|
|
to: config.build.assetsRoot,
|
|
|
|
|
ignore: ['.*']
|
|
|
|
|
}
|
|
|
|
|
]),
|
|
|
|
|
// Only keep the useful locales from Moment.
|
|
|
|
|
new webpack.IgnorePlugin(/^\.\/locale$/, /moment$/),
|
|
|
|
|
],
|
2018-06-25 18:29:57 +02:00
|
|
|
|
}
|