UNPKG

3.96 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';
11
12export default {
13 devtool: 'cheap-module-eval-source-map',
14 mode: 'development',
15 entry: {
16 app: ['webpack-hot-middleware/client', 'react-hot-loader/patch', './src/index.js'],
17 },
18 output: {
19 path: path.join(__dirname, '_public'),
20 filename: '[name].bundle.js',
21 publicPath: '/',
22 },
23 plugins: [
24 new webpack.HotModuleReplacementPlugin(),
25 new webpack.DefinePlugin({
26 'process.env': env,
27 }),
28 new HtmlWebpackPlugin({
29 template: './src/index.html',
30 chunksSortMode: 'dependency',
31 }),
32 ],
33 optimization: {
34 minimizer: [
35 new TerserPlugin({
36 terserOptions: {
37 ecma: 5,
38 compress: {
39 warnings: false,
40 comparisons: false,
41 },
42 output: {
43 comments: false,
44 ascii_only: false,
45 },
46 },
47 }),
48 ],
49 // Automatically split vendor and commons
50 // https://hackernoon.com/the-100-correct-way-to-split-your-chunks-with-webpack-f8a9df5b7758
51 splitChunks: {
52 chunks: 'all',
53 maxInitialRequests: Infinity,
54 minSize: 0,
55 cacheGroups: {
56 vendor: {
57 test: /[\\/]node_modules[\\/]/,
58 name: 'vendors',
59 chunks: 'all',
60 },
61 },
62 },
63 runtimeChunk: 'single',
64 },
65 module: {
66 rules: [
67 {
68 test: /\.js?$/,
69 include: path.join(__dirname, 'src'),
70 exclude: path.join(__dirname, 'node_modules'),
71 loader: 'babel-loader',
72 options: {
73 presets: [
74 ['@babel/preset-env', { loose: true, modules: false, useBuiltIns: 'usage', corejs: 2 }],
75 '@babel/preset-react',
76 ],
77 plugins: [
78 'react-hot-loader/babel',
79 '@babel/plugin-syntax-dynamic-import',
80 '@babel/plugin-syntax-import-meta',
81 '@babel/plugin-proposal-class-properties',
82 '@babel/plugin-proposal-json-strings',
83 '@babel/plugin-transform-react-constant-elements',
84 ],
85 babelrc: false,
86 },
87 },
88 {
89 test: /\.css$/,
90 include: path.join(__dirname, 'src'),
91 use: [
92 { loader: 'style-loader', options: { sourceMap: true } },
93 {
94 loader: 'css-loader',
95 options: {
96 camelCase: true,
97 modules: true,
98 importLoaders: 1,
99 localIdentName: '[name]__[local]___[hash:base64:5]',
100 sourceMap: true,
101 },
102 },
103 {
104 loader: 'postcss-loader',
105 options: {
106 sourceMap: 'inline',
107 plugins: () => [
108 atImport(),
109 postcssPresetEnv({
110 stage: 0,
111 importFrom: [
112 {
113 customMedia: media,
114 customProperties: palette,
115 },
116 ],
117 preserve: false,
118 }),
119 ],
120 },
121 },
122 ],
123 },
124 {
125 test: /\.css$/,
126 include: path.join(__dirname, 'node_modules'),
127 use: [
128 { loader: 'style-loader', options: { sourceMap: true } },
129 { loader: 'css-loader', options: { sourceMap: true } },
130 ],
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};