UNPKG

5.34 kBJavaScriptView Raw
1const webpack = require("webpack");
2const fs = require("fs");
3const path = require("path");
4const OptimizeCssAssetsPlugin = require("optimize-css-assets-webpack-plugin");
5const MiniCssExtractPlugin = require("mini-css-extract-plugin");
6const ManifestPlugin = require("webpack-manifest-plugin");
7const DuplicatePackageCheckerPlugin = require("duplicate-package-checker-webpack-plugin");
8
9const LodashModuleReplacementPlugin = require("lodash-webpack-plugin");
10
11function 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
36function 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
46function getBabelConfig() {
47 return {
48 loader: "babel-loader",
49 options: {
50 // this is to ensure any existing babelrc configs in any file relative paths are ignored
51 babelrc: false,
52 plugins: ["lodash"],
53 // this path needs to be relative to this file and not PWD
54 configFile: path.resolve(__dirname, "./babel.js"),
55 sourceType: "unambiguous"
56 }
57 };
58}
59
60function 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
80function 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
95function 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
110function 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
179module.exports = { getConfig };