kalker/kalk_web/webpack.config.ts

215 lines
5.4 KiB
TypeScript

import path from 'path';
import MiniCssExtractPlugin from 'mini-css-extract-plugin';
import OptimizeCSSAssetsPlugin from 'optimize-css-assets-webpack-plugin';
import TerserPlugin from 'terser-webpack-plugin';
import { CleanWebpackPlugin } from 'clean-webpack-plugin';
import Preprocess from 'svelte-preprocess';
import webpack from 'webpack';
import WebpackDevServer from 'webpack-dev-server';
const mode =
(process.env.NODE_ENV as 'production' | 'development') || 'development';
const prod = mode === 'production';
const sveltePath = path.resolve('node_modules', 'svelte');
/**
* Should source maps be generated alongside your production bundle? This will expose your raw source code, so it's
* disabled by default.
*/
const sourceMapsInProduction = false;
/**
* Should we run Babel on builds? This will transpile your bundle in order to work on your target browsers (see the
* `browserslist` property in your package.json), but will impact bundle size and build speed.
*/
const useBabel = false;
/**
* Should we run Babel on development builds? If set to `false`, only production builds will be transpiled. If you're
* only testing in modern browsers and don't need transpiling in development, it is recommended to keep this disabled
* as it will greatly speed up your builds.
*/
const useBabelInDevelopment = false;
const config: webpack.Configuration & WebpackDevServer.Configuration = {
entry: {
bundle: [
'./src/main.ts',
],
},
resolve: {
alias: {
// Note: Additional aliases will be loaded automatically from `tsconfig.compilerOptions.paths`
svelte: path.resolve('node_modules', 'svelte'),
},
extensions: ['.mjs', '.js', '.ts', '.svelte'],
mainFields: ['svelte', 'browser', 'module', 'main'],
},
output: {
publicPath: prod ? '' : '/build/',
path: __dirname + '/public/build',
filename: '[name].js',
chunkFilename: '[name].[id].js',
library: "kalkComponent",
libraryTarget: 'window',
libraryExport: 'default'
},
module: {
rules: [
{
test: /\.svelte$/,
use: {
loader: 'svelte-loader-hot',
options: {
customElement: true,
dev: !prod,
emitCss: prod,
hotReload: !prod,
hotOptions: {
// List of options and defaults: https://www.npmjs.com/package/svelte-loader-hot#usage
noPreserveState: false,
optimistic: true,
},
preprocess: Preprocess({
scss: true,
postcss: {
plugins: [require('autoprefixer')],
},
}),
},
},
},
{
test: /\.(scss|sass)$/,
use: [
{
loader: MiniCssExtractPlugin.loader,
options: {
hmr: !prod,
sourceMap: !prod || sourceMapsInProduction,
},
},
'css-loader',
{
loader: 'postcss-loader',
options: {
plugins: [require('autoprefixer')],
},
},
'sass-loader',
],
},
{
test: /\.css$/,
use: [
{
loader: MiniCssExtractPlugin.loader,
options: {
hmr: !prod,
sourceMap: !prod || sourceMapsInProduction,
},
},
'css-loader',
],
},
{
test: /\.ts$/,
use: 'ts-loader',
exclude: /node_modules/,
},
],
},
devServer: {
hot: true,
stats: 'minimal',
contentBase: 'public',
watchContentBase: true,
},
mode,
plugins: [
new MiniCssExtractPlugin({
filename: '[name].css',
}),
],
optimization: {
minimizer: [],
},
devtool: prod && !sourceMapsInProduction ? false : 'source-map',
};
// Load path mapping from tsconfig
const tsconfigPath = path.resolve(__dirname, 'tsconfig.json');
const tsconfig = require('fs').existsSync(tsconfigPath) ? require(tsconfigPath) : {};
if ('compilerOptions' in tsconfig && 'paths' in tsconfig.compilerOptions) {
const aliases = tsconfig.compilerOptions.paths;
for (const alias in aliases) {
const paths = aliases[alias].map((p: string) => path.resolve(__dirname, p));
// Our tsconfig uses glob path formats, whereas webpack just wants directories
// We'll need to transform the glob format into a format acceptable to webpack
const wpAlias = alias.replace(/(\\|\/)\*$/, '');
const wpPaths = paths.map((p: string) => p.replace(/(\\|\/)\*$/, ''));
if (!(wpAlias in config.resolve.alias) && wpPaths.length) {
config.resolve.alias[wpAlias] = wpPaths.length > 1 ? wpPaths : wpPaths[0];
}
}
}
// These options should only apply to production builds
if (prod) {
// Clean the build directory for production builds
config.plugins.push(new CleanWebpackPlugin());
// Minify CSS
config.optimization.minimizer.push(
new OptimizeCSSAssetsPlugin({
cssProcessorOptions: {
map: sourceMapsInProduction
? {
inline: false,
annotation: true,
}
: false,
},
cssProcessorPluginOptions: {
preset: [
'default',
{
discardComments: {
removeAll: !sourceMapsInProduction,
},
},
],
},
})
);
// Minify and treeshake JS
config.optimization.minimizer.push(
new TerserPlugin({
sourceMap: sourceMapsInProduction,
extractComments: false,
})
);
}
// Add babel if enabled
if (useBabel && (prod || useBabelInDevelopment)) {
config.module.rules.unshift({
test: /\.(?:svelte|m?js)$/,
include: [path.resolve(__dirname, 'src'), path.dirname(sveltePath)],
use: {
loader: 'babel-loader',
options: {
sourceType: 'unambiguous',
presets: ['@babel/preset-env'],
plugins: ['@babel/plugin-transform-runtime'],
},
},
});
}
export default config;