1 | const webpack = require("webpack");
|
2 | const fs = require("fs");
|
3 | const path = require("path");
|
4 | const OptimizeCssAssetsPlugin = require("optimize-css-assets-webpack-plugin");
|
5 | const MiniCssExtractPlugin = require("mini-css-extract-plugin");
|
6 | const ManifestPlugin = require("webpack-manifest-plugin");
|
7 | const DuplicatePackageCheckerPlugin = require("duplicate-package-checker-webpack-plugin");
|
8 |
|
9 | const LodashModuleReplacementPlugin = require("lodash-webpack-plugin");
|
10 |
|
11 | function getCssModuleConfig({ env = "development" }) {
|
12 | const extractLoader =
|
13 | env === "production"
|
14 | ? MiniCssExtractPlugin.loader
|
15 | : { loader: "style-loader" };
|
16 | const cssLoader = {
|
17 | loader: "css-loader",
|
18 | options: {
|
19 | sourceMap: true,
|
20 | modules: true,
|
21 | importLoaders: 1,
|
22 | localIdentName: "[name]__[local]__[hash:base64:5]"
|
23 | }
|
24 | };
|
25 | const preProcessCssLoader = {
|
26 | loader: "postcss-loader",
|
27 | options: {
|
28 | ident: "postcss",
|
29 | sourceMap: true,
|
30 | plugins: loader => [require("precss")(), require("autoprefixer")]
|
31 | }
|
32 | };
|
33 | return [extractLoader, cssLoader, preProcessCssLoader];
|
34 | }
|
35 |
|
36 | function getSassConfig({ env = "development" }) {
|
37 | return [
|
38 | env === "production"
|
39 | ? MiniCssExtractPlugin.loader
|
40 | : { loader: "style-loader" },
|
41 | { loader: "css-loader", options: { sourceMap: true } },
|
42 | { loader: "sass-loader", options: { sourceMap: true } }
|
43 | ];
|
44 | }
|
45 |
|
46 | function getBabelConfig() {
|
47 | return {
|
48 | loader: "babel-loader",
|
49 | options: {
|
50 |
|
51 | babelrc: false,
|
52 | plugins: ["lodash"],
|
53 |
|
54 | configFile: path.resolve(__dirname, "./babel.js"),
|
55 | sourceType: "unambiguous"
|
56 | }
|
57 | };
|
58 | }
|
59 |
|
60 | function entryFiles(opts) {
|
61 | let entryFiles = {};
|
62 |
|
63 | if (fs.existsSync("./app/client/polyfill.js")) {
|
64 | entryFiles["polyfill"] = "./app/client/polyfill.js";
|
65 | }
|
66 |
|
67 | entryFiles = Object.assign(
|
68 | {},
|
69 | entryFiles,
|
70 | {
|
71 | app: "./app/client/app.js",
|
72 | serviceWorkerHelper: "./app/client/serviceWorkerHelper.sjs"
|
73 | },
|
74 | opts.entryFiles
|
75 | );
|
76 |
|
77 | return entryFiles;
|
78 | }
|
79 |
|
80 | function getProductionConfig(opts) {
|
81 | const sassConfig = getSassConfig({ ...opts, env: "production" });
|
82 | const cssModuleConfig = getCssModuleConfig({ ...opts, env: "production" });
|
83 | const PUBLIC_PATH = `/${opts.publisherName}/assets/`;
|
84 | return {
|
85 | outputFileName: suffix => `[name]-[hash:20].${suffix}`,
|
86 | sassConfig,
|
87 | cssModuleConfig,
|
88 | cssFile: `[name]-[contenthash:20].css`,
|
89 | compressCSSPlugins: [new OptimizeCssAssetsPlugin()],
|
90 | outputPublicPath: PUBLIC_PATH,
|
91 | sourceMapType: "source-map"
|
92 | };
|
93 | }
|
94 |
|
95 | function getDevelopmentConfig(opts) {
|
96 | const sassConfig = getSassConfig({ ...opts, env: "development" });
|
97 | const cssModuleConfig = getCssModuleConfig({ ...opts, env: "development" });
|
98 | const PUBLIC_PATH = `/${opts.publisherName}/assets/`;
|
99 | return {
|
100 | outputFileName: suffix => `[name].${suffix}`,
|
101 | sassConfig,
|
102 | cssModuleConfig,
|
103 | cssFile: `[name].css`,
|
104 | compressCSSPlugins: [],
|
105 | outputPublicPath: "http://localhost:8080" + PUBLIC_PATH,
|
106 | sourceMapType: "eval-source-map"
|
107 | };
|
108 | }
|
109 |
|
110 | function getConfig(opts) {
|
111 | const PUBLIC_PATH = `/${opts.publisherName}/assets/`;
|
112 | const OUTPUT_DIRECTORY = path.resolve(`./public/${PUBLIC_PATH}`);
|
113 | const config =
|
114 | opts.env === "production"
|
115 | ? getProductionConfig(opts)
|
116 | : getDevelopmentConfig(opts);
|
117 | return {
|
118 | entry: entryFiles(opts),
|
119 | mode: opts.env === "production" ? "production" : "development",
|
120 | output: {
|
121 | path: OUTPUT_DIRECTORY,
|
122 | filename: config.outputFileName("js"),
|
123 | publicPath: config.outputPublicPath
|
124 | },
|
125 | module: {
|
126 | rules: [
|
127 | { test: /\.jsx?$/, exclude: /node_modules/, use: getBabelConfig(opts) },
|
128 | {
|
129 | test: /\.jsx?$/,
|
130 | include: /node_modules\/@quintype\/framework/,
|
131 | use: getBabelConfig(opts)
|
132 | },
|
133 | {
|
134 | test: /\.jsx?$/,
|
135 | include: /node_modules\/@quintype\/components\/store/,
|
136 | use: getBabelConfig(opts)
|
137 | },
|
138 | { test: /\.(sass|scss)$/, use: config.sassConfig },
|
139 | { test: /\.module.css$/, use: config.cssModuleConfig },
|
140 | { test: /\.m.css$/, use: config.cssModuleConfig },
|
141 | {
|
142 | test: /\.(jpe?g|gif|png|svg|woff|woff2|eot|ttf|wav|mp3|ico|mp4)$/,
|
143 | loader: "file-loader",
|
144 | query: {
|
145 | context: "./app/assets",
|
146 | name: config.outputFileName("[ext]")
|
147 | }
|
148 | }
|
149 | ]
|
150 | },
|
151 | plugins: [
|
152 | new LodashModuleReplacementPlugin({
|
153 | paths: true
|
154 | }),
|
155 | new webpack.EnvironmentPlugin({ NODE_ENV: "development" }),
|
156 | new MiniCssExtractPlugin({ filename: config.cssFile }),
|
157 | new ManifestPlugin({
|
158 | map(asset) {
|
159 | return Object.assign(asset, {
|
160 | path: asset.path.replace(config.outputPublicPath, PUBLIC_PATH)
|
161 | });
|
162 | },
|
163 | fileName: "../../../asset-manifest.json",
|
164 | publicPath: PUBLIC_PATH,
|
165 | writeToFileEmit: true
|
166 | }),
|
167 | new DuplicatePackageCheckerPlugin({
|
168 | verbose: true
|
169 | })
|
170 | ].concat(config.compressCSSPlugins),
|
171 |
|
172 | devServer: {
|
173 | headers: { "Access-Control-Allow-Origin": "*" }
|
174 | },
|
175 | devtool: config.sourceMapType
|
176 | };
|
177 | }
|
178 |
|
179 | module.exports = { getConfig };
|