You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
wiki/dev/webpack/webpack.dev.js

282 lines
7.0 KiB

const webpack = require('webpack')
const path = require('path')
const fs = require('fs-extra')
const yargs = require('yargs').argv
const _ = require('lodash')
const { VueLoaderPlugin } = require('vue-loader')
const CopyWebpackPlugin = require('copy-webpack-plugin')
const HtmlWebpackPlugin = require('html-webpack-plugin')
const HtmlWebpackPugPlugin = require('html-webpack-pug-plugin')
const MomentTimezoneDataPlugin = require('moment-timezone-data-webpack-plugin')
const VuetifyLoaderPlugin = require('vuetify-loader/lib/plugin')
const WriteFilePlugin = require('write-file-webpack-plugin')
const WebpackBarPlugin = require('webpackbar')
const babelConfig = fs.readJsonSync(path.join(process.cwd(), '.babelrc'))
const cacheDir = '.webpack-cache/cache'
const babelDir = path.join(process.cwd(), '.webpack-cache/babel')
process.noDeprecation = true
fs.emptyDirSync(path.join(process.cwd(), 'assets'))
module.exports = {
mode: 'development',
entry: {
app: ['./client/index-app.js', 'webpack-hot-middleware/client'],
legacy: ['./client/index-legacy.js', 'webpack-hot-middleware/client'],
setup: ['./client/index-setup.js', 'webpack-hot-middleware/client']
},
output: {
path: path.join(process.cwd(), 'assets'),
publicPath: '/_assets/',
filename: 'js/[name].js',
chunkFilename: 'js/[name].js',
globalObject: 'this',
pathinfo: true,
crossOriginLoading: 'use-credentials'
},
module: {
rules: [
{
test: /\.js$/,
exclude: (modulePath) => {
return modulePath.includes('node_modules') && !modulePath.includes('vuetify')
},
use: [
{
loader: 'cache-loader',
options: {
cacheDirectory: cacheDir
}
},
{
loader: 'babel-loader',
options: {
...babelConfig,
cacheDirectory: babelDir
}
}
]
},
{
test: /\.css$/,
use: [
'style-loader',
'css-loader',
'postcss-loader'
]
},
{
test: /\.sass$/,
use: [
{
loader: 'cache-loader',
options: {
cacheDirectory: cacheDir
}
},
'style-loader',
'css-loader',
'postcss-loader',
{
loader: 'sass-loader',
options: {
implementation: require('sass'),
sourceMap: false
}
}
]
},
{
test: /\.scss$/,
use: [
{
loader: 'cache-loader',
options: {
cacheDirectory: cacheDir
}
},
'style-loader',
'css-loader',
'postcss-loader',
{
loader: 'sass-loader',
options: {
implementation: require('sass'),
sourceMap: false
}
},
{
loader: 'sass-resources-loader',
options: {
resources: path.join(process.cwd(), '/client/scss/global.scss')
}
}
]
},
{
test: /\.vue$/,
loader: 'vue-loader'
},
{
test: /\.pug$/,
exclude: [
path.join(process.cwd(), 'dev')
],
loader: 'pug-plain-loader'
},
{
test: /\.(png|jpg|gif)$/,
use: [
{
loader: 'url-loader',
options: {
limit: 8192
}
}
]
},
{
test: /\.svg$/,
exclude: [
path.join(process.cwd(), 'node_modules/grapesjs')
],
use: [
{
loader: 'file-loader',
options: {
name: '[name].[ext]',
outputPath: 'svg/'
}
}
]
},
{
test: /\.(graphql|gql)$/,
exclude: /node_modules/,
use: [
{ loader: 'graphql-persisted-document-loader' },
{ loader: 'graphql-tag/loader' }
]
},
{
test: /\.(woff(2)?|ttf|eot|svg)(\?v=\d+\.\d+\.\d+)?$/,
exclude: [
path.join(process.cwd(), 'client')
],
use: [{
loader: 'file-loader',
options: {
name: '[name].[ext]',
outputPath: 'fonts/'
}
}]
},
{
loader: 'webpack-modernizr-loader',
test: /\.modernizrrc\.js$/
}
]
},
plugins: [
new VueLoaderPlugin(),
new VuetifyLoaderPlugin(),
new MomentTimezoneDataPlugin({
startYear: 2017,
endYear: (new Date().getFullYear()) + 5
}),
new CopyWebpackPlugin({
patterns: [
{ from: 'client/static' },
{ from: './node_modules/prismjs/components', to: 'js/prism' }
]
}),
new HtmlWebpackPlugin({
template: 'dev/templates/master.pug',
filename: '../server/views/master.pug',
hash: false,
inject: false,
excludeChunks: ['setup', 'legacy']
}),
new HtmlWebpackPlugin({
template: 'dev/templates/legacy.pug',
filename: '../server/views/legacy/master.pug',
hash: false,
inject: false,
excludeChunks: ['setup', 'app']
}),
new HtmlWebpackPlugin({
template: 'dev/templates/setup.pug',
filename: '../server/views/setup.pug',
hash: false,
inject: false,
excludeChunks: ['app', 'legacy']
}),
new HtmlWebpackPugPlugin(),
new WebpackBarPlugin({
name: 'Client Assets'
}),
new webpack.DefinePlugin({
'process.env.NODE_ENV': JSON.stringify('development'),
'process.env.CURRENT_THEME': JSON.stringify(_.defaultTo(yargs.theme, 'default'))
}),
new WriteFilePlugin(),
new webpack.HotModuleReplacementPlugin(),
new webpack.WatchIgnorePlugin([
/node_modules/
])
],
optimization: {
namedModules: true,
namedChunks: true,
splitChunks: {
cacheGroups: {
default: {
minChunks: 2,
priority: -20,
reuseExistingChunk: true
},
vendor: {
test: /[\\/]node_modules[\\/]/,
minChunks: 2,
priority: -10
}
}
},
runtimeChunk: 'single'
},
resolve: {
mainFields: ['browser', 'main', 'module'],
symlinks: true,
alias: {
'@': path.join(process.cwd(), 'client'),
'vue$': 'vue/dist/vue.esm.js',
'gql': path.join(process.cwd(), 'client/graph'),
// Duplicates fixes:
'apollo-link': path.join(process.cwd(), 'node_modules/apollo-link'),
'apollo-utilities': path.join(process.cwd(), 'node_modules/apollo-utilities'),
'uc.micro': path.join(process.cwd(), 'node_modules/uc.micro'),
'modernizr$': path.resolve(process.cwd(), 'client/.modernizrrc.js')
},
extensions: [
'.js',
'.json',
'.vue'
],
modules: [
'node_modules'
]
},
node: {
fs: 'empty'
},
stats: {
children: false,
entrypoints: false
},
target: 'web',
watch: true
}