sveltejs / sapper-template

Starter template for Sapper apps
703 stars 215 forks source link

DRY out default Webpack config #280

Open madeleineostoja opened 3 years ago

madeleineostoja commented 3 years ago

Is your feature request related to a problem? Please describe. Not a bug or large problem, but I just span up a new Sapper project and it struck me that the webpack configuration in the default template had a lot of unnecessary repetition, making modifications cumbersome for end users.

Describe the solution you'd like A minor refactor of webpack.config.js in the default Sapper webpack template, to make things a little easier to reason about and for end users to hack around on to add additional loaders etc needed for their environment.

Something like this as a starting point

const webpack = require('webpack');
const WebpackModules = require('webpack-modules');
const path = require('path');
const config = require('sapper/config/webpack.js');
const pkg = require('./package.json');
const sveltePreprocess = require('svelte-preprocess');

const mode = process.env.NODE_ENV,
  dev = mode === 'development',
  resolve = {
    alias: { svelte: path.resolve('node_modules', 'svelte') },
    extensions: ['.mjs', '.js', '.json', '.svelte', '.html'],
    mainFields: ['svelte', 'module', 'browser', 'main']
  },
  svelteConfig = (opts) => ({
    test: /\.(svelte|html)$/,
    use: [
      {
        loader: 'svelte-loader',
        options: {
          dev,
          hydratable: true,
          preprocess: sveltePreprocess(),
          ...opts
        }
      }
    ]
  }),
  sharedRules = [
    {
      test: /\.(png|jpe?g|gif)$/i,
      use: ['file-loader']
    }
  ];

module.exports = {
  client: {
    entry: config.client.entry(),
    output: config.client.output(),
    resolve,
    module: {
      rules: [
        svelteConfig(),
        ...sharedRules
      ]
    },
    mode,
    plugins: [
      dev && new webpack.HotModuleReplacementPlugin(),
      new webpack.DefinePlugin({
        'process.browser': true,
        'process.env.NODE_ENV': JSON.stringify(mode)
      })
    ].filter(Boolean),
    devtool: dev && 'inline-source-map'
  },

  server: {
    entry: config.server.entry(),
    output: config.server.output(),
    target: 'node',
    resolve,
    externals: Object.keys(pkg.dependencies).concat('encoding'),
    module: {
      rules: [
        {
          ...svelteConfig({,
            css: false,
            generate: 'ssr'
          })
        },
        ...sharedRules
      ]
    },
    mode,
    plugins: [new WebpackModules()],
    performance: {
      hints: false // it doesn't matter if server.js is large
    }
  },

  serviceworker: {
    entry: config.serviceworker.entry(),
    output: config.serviceworker.output(),
    mode
  }
};

For my own config I've added several rules to sharedRules as well as modified the base svelte loader config with preprocessing etc.

How important is this feature to you? Not very to be honest, it's just to make it easier for developers to wrangle webpack in the default template. Currently the default webpack conf feels quite intimidating.