UNPKG

3.99 kBJavaScriptView Raw
1import path from 'path';
2import webpack from 'webpack';
3import atImport from 'postcss-import';
4import postcssPresetEnv from 'postcss-preset-env';
5import HtmlWebpackPlugin from 'html-webpack-plugin';
6import TerserPlugin from 'terser-webpack-plugin';
7
8import palette from './config/palette';
9import media from './config/media';
10import env from './config/env';
11import endpoint from './config/endpoint';
12
13export default {
14 devtool: 'cheap-module-eval-source-map',
15 mode: 'development',
16 entry: {
17 app: ['webpack-hot-middleware/client', 'react-hot-loader/patch', './src/index.js'],
18 },
19 output: {
20 path: path.join(__dirname, '_public'),
21 filename: '[name].bundle.js',
22 publicPath: '/',
23 },
24 plugins: [
25 new webpack.HotModuleReplacementPlugin(),
26 new webpack.DefinePlugin({
27 'process.env': { ...env, ...endpoint },
28 }),
29 new HtmlWebpackPlugin({
30 template: './src/index.html',
31 chunksSortMode: 'dependency',
32 }),
33 ],
34 optimization: {
35 minimizer: [
36 new TerserPlugin({
37 terserOptions: {
38 ecma: 5,
39 compress: {
40 warnings: false,
41 comparisons: false,
42 },
43 output: {
44 comments: false,
45 ascii_only: false,
46 },
47 },
48 }),
49 ],
50 // Automatically split vendor and commons
51 // https://hackernoon.com/the-100-correct-way-to-split-your-chunks-with-webpack-f8a9df5b7758
52 splitChunks: {
53 chunks: 'all',
54 maxInitialRequests: Infinity,
55 minSize: 0,
56 cacheGroups: {
57 vendor: {
58 test: /[\\/]node_modules[\\/]/,
59 name: 'vendors',
60 chunks: 'all',
61 },
62 },
63 },
64 runtimeChunk: 'single',
65 },
66 module: {
67 rules: [
68 {
69 test: /\.js?$/,
70 include: path.join(__dirname, 'src'),
71 exclude: path.join(__dirname, 'node_modules'),
72 loader: 'babel-loader',
73 options: {
74 presets: [
75 ['@babel/preset-env', { loose: true, modules: false, useBuiltIns: 'usage', corejs: 3 }],
76 '@babel/preset-react',
77 ],
78 plugins: [
79 'react-hot-loader/babel',
80 ['module-resolver', { root: ['./src'] }],
81 '@babel/plugin-syntax-dynamic-import',
82 '@babel/plugin-syntax-import-meta',
83 '@babel/plugin-proposal-class-properties',
84 '@babel/plugin-proposal-json-strings',
85 '@babel/plugin-transform-react-constant-elements',
86 ],
87 babelrc: false,
88 },
89 },
90 {
91 test: /\.css$/,
92 include: path.join(__dirname, 'src'),
93 use: [
94 'style-loader',
95 {
96 loader: 'css-loader',
97 options: {
98 localsConvention: 'camelCase',
99 modules: {
100 localIdentName: '[name]__[local]___[hash:base64:5]',
101 },
102 importLoaders: 1,
103 sourceMap: true,
104 },
105 },
106 {
107 loader: 'postcss-loader',
108 options: {
109 sourceMap: 'inline',
110 plugins: () => [
111 atImport(),
112 postcssPresetEnv({
113 stage: 0,
114 importFrom: [
115 {
116 customMedia: media,
117 customProperties: palette,
118 },
119 ],
120 preserve: false,
121 }),
122 ],
123 },
124 },
125 ],
126 },
127 {
128 test: /\.css$/,
129 include: path.join(__dirname, 'node_modules'),
130 use: ['style-loader', { loader: 'css-loader', options: { sourceMap: true } }],
131 },
132 {
133 test: /\.(jpe?g|png|gif)$/,
134 include: path.join(__dirname, 'src'),
135 loader: 'url-loader',
136 options: {
137 limit: 10000,
138 name: './assets/[name]__[hash].[ext]',
139 },
140 },
141 {
142 test: /^(?!.*\.inline\.svg$).*\.svg$/,
143 include: path.join(__dirname, 'src'),
144 use: [
145 '@svgr/webpack',
146 {
147 loader: 'url-loader',
148 options: {
149 limit: 10000,
150 name: './assets/[name]__[hash].[ext]',
151 },
152 },
153 ],
154 },
155 {
156 test: /\.inline.svg$/,
157 include: path.join(__dirname, 'src'),
158 loader: '@svgr/webpack',
159 options: {
160 svgoConfig: {
161 plugins: [{ cleanupIDs: false }, { removeViewBox: false }],
162 },
163 },
164 },
165 ],
166 },
167 node: {
168 fs: 'empty',
169 },
170 resolve: {
171 modules: ['node_modules'],
172 alias: {
173 'react-dom': '@hot-loader/react-dom',
174 },
175 },
176};