import ExtractTextPlugin from 'extract-text-webpack-plugin' import { defaults, cloneDeep } from 'lodash' import { join, resolve } from 'path' import webpack from 'webpack' import { isUrl, urlJoin } from 'utils' import autoprefixer from 'autoprefixer' import vueLoaderConfig from './vue-loader.config' import { styleLoader, extractStyles } from './helpers' /* |-------------------------------------------------------------------------- | Webpack Shared Config | | This is the config which is extended by the server and client | webpack config files |-------------------------------------------------------------------------- */ export default function webpackBaseConfig ({ isClient, isServer }) { const nodeModulesDir = join(__dirname, '..', 'node_modules') if (!Array.isArray(this.options.build.postcss)) { this.options.build.postcss = [ autoprefixer({ browsers: ['last 3 versions'] }) ] } const config = { devtool: this.options.dev ? 'cheap-module-source-map' : false, entry: { vendor: ['vue', 'vue-router', 'vue-meta'] }, output: { path: resolve(this.options.buildDir, 'dist'), filename: this.options.build.filenames.app, publicPath: (isUrl(this.options.build.publicPath) ? this.options.build.publicPath : urlJoin(this.options.router.base, this.options.build.publicPath)) }, performance: { maxEntrypointSize: 300000, maxAssetSize: 300000, hints: this.options.dev ? false : 'warning' }, resolve: { extensions: ['.js', '.json', '.vue', '.ts'], // Disable for now alias: { '~': join(this.options.srcDir), 'static': join(this.options.srcDir, 'static'), // use in template with '~static': join(this.options.srcDir, 'static'), 'assets': join(this.options.srcDir, 'assets'), // use in template with '~assets': join(this.options.srcDir, 'assets'), '~plugins': join(this.options.srcDir, 'plugins'), '~store': join(this.options.buildDir, 'store'), '~router': join(this.options.buildDir, 'router'), '~pages': join(this.options.srcDir, 'pages'), '~components': join(this.options.srcDir, 'components') }, modules: [ join(this.options.rootDir, 'node_modules'), nodeModulesDir ] }, resolveLoader: { modules: [ join(this.options.rootDir, 'node_modules'), nodeModulesDir ] }, module: { noParse: /es6-promise\.js$/, // avoid webpack shimming process rules: [ { test: /\.vue$/, loader: 'vue-loader', query: vueLoaderConfig.call(this, { isClient, isServer }) }, { test: /\.js$/, loader: 'babel-loader', exclude: /node_modules/, query: defaults(this.options.build.babel, { presets: ['vue-app'], babelrc: false, cacheDirectory: !!this.options.dev }) }, { test: /\.css$/, use: styleLoader.call(this, 'css') }, { test: /\.less$/, use: styleLoader.call(this, 'less', 'less-loader') }, { test: /\.sass$/, use: styleLoader.call(this, 'sass', 'sass-loader?indentedSyntax&sourceMap') }, { test: /\.scss$/, use: styleLoader.call(this, 'sass', 'sass-loader?sourceMap') }, { test: /\.styl(us)?$/, use: styleLoader.call(this, 'stylus', 'stylus-loader') }, { test: /\.(png|jpe?g|gif|svg)$/, loader: 'url-loader', query: { limit: 1000, // 1KO name: 'img/[name].[hash:7].[ext]' } }, { test: /\.(woff2?|eot|ttf|otf)(\?.*)?$/, loader: 'url-loader', query: { limit: 1000, // 1 KO name: 'fonts/[name].[hash:7].[ext]' } } ] }, plugins: this.options.build.plugins } // CSS extraction if (extractStyles.call(this)) { config.plugins.push( new ExtractTextPlugin({ filename: this.options.build.filenames.css }) ) } // -------------------------------------- // Dev specific config // -------------------------------------- if (this.options.dev) { // } // -------------------------------------- // Production specific config // -------------------------------------- if (!this.options.dev) { // This is needed in webpack 2 for minify CSS config.plugins.push( new webpack.LoaderOptionsPlugin({ minimize: true }) ) } // Clone deep avoid leaking config between Client and Server return cloneDeep(config) }