| 1 | let path = require('path'); |
||
| 2 | let glob = require('glob'); |
||
| 3 | let webpack = require('webpack'); |
||
| 4 | let Mix = require('laravel-mix').config; |
||
| 5 | let webpackPlugins = require('laravel-mix').plugins; |
||
| 6 | let dotenv = require('dotenv') |
||
| 7 | |||
| 8 | /* |
||
| 9 | |-------------------------------------------------------------------------- |
||
| 10 | | Load Environment Variables |
||
| 11 | |-------------------------------------------------------------------------- |
||
| 12 | | |
||
| 13 | | Load environment variables from .env file. dotenv will never modify |
||
| 14 | | any environment variables that have already been set. |
||
| 15 | | |
||
| 16 | */ |
||
| 17 | |||
| 18 | dotenv.config({ |
||
| 19 | path: Mix.Paths.root('.env') |
||
| 20 | }); |
||
| 21 | |||
| 22 | |||
| 23 | |||
| 24 | /* |
||
| 25 | |-------------------------------------------------------------------------- |
||
| 26 | | Mix Initialization |
||
| 27 | |-------------------------------------------------------------------------- |
||
| 28 | | |
||
| 29 | | As our first step, we'll require the project's Laravel Mix file |
||
| 30 | | and record the user's requested compilation and build steps. |
||
| 31 | | Once those steps have been recorded, we may get to work. |
||
| 32 | | |
||
| 33 | */ |
||
| 34 | |||
| 35 | Mix.initialize(); |
||
| 36 | |||
| 37 | |||
| 38 | |||
| 39 | /* |
||
| 40 | |-------------------------------------------------------------------------- |
||
| 41 | | Webpack Context |
||
| 42 | |-------------------------------------------------------------------------- |
||
| 43 | | |
||
| 44 | | This prop will determine the appropriate context, when running Webpack. |
||
| 45 | | Since you have the option of publishing this webpack.config.js file |
||
| 46 | | to your project root, we will dynamically set the path for you. |
||
| 47 | | |
||
| 48 | */ |
||
| 49 | |||
| 50 | module.exports.context = Mix.Paths.root(); |
||
| 51 | |||
| 52 | |||
| 53 | |||
| 54 | /* |
||
| 55 | |-------------------------------------------------------------------------- |
||
| 56 | | Webpack Entry |
||
| 57 | |-------------------------------------------------------------------------- |
||
| 58 | | |
||
| 59 | | We'll first specify the entry point for Webpack. By default, we'll |
||
| 60 | | assume a single bundled file, but you may call Mix.extract() |
||
| 61 | | to make a separate bundle specifically for vendor libraries. |
||
| 62 | | |
||
| 63 | */ |
||
| 64 | |||
| 65 | module.exports.entry = Mix.entry().get(); |
||
| 66 | |||
| 67 | |||
| 68 | |||
| 69 | /* |
||
| 70 | |-------------------------------------------------------------------------- |
||
| 71 | | Webpack Output |
||
| 72 | |-------------------------------------------------------------------------- |
||
| 73 | | |
||
| 74 | | Webpack naturally requires us to specify our desired output path and |
||
| 75 | | file name. We'll simply echo what you passed to with Mix.js(). |
||
| 76 | | Note that, for Mix.version(), we'll properly hash the file. |
||
| 77 | | |
||
| 78 | */ |
||
| 79 | |||
| 80 | module.exports.output = Mix.output(); |
||
| 81 | |||
| 82 | |||
| 83 | |||
| 84 | /* |
||
| 85 | |-------------------------------------------------------------------------- |
||
| 86 | | Rules |
||
| 87 | |-------------------------------------------------------------------------- |
||
| 88 | | |
||
| 89 | | Webpack rules allow us to register any number of loaders and options. |
||
| 90 | | Out of the box, we'll provide a handful to get you up and running |
||
| 91 | | as quickly as possible, though feel free to add to this list. |
||
| 92 | | |
||
| 93 | */ |
||
| 94 | |||
| 95 | let plugins = []; |
||
| 96 | |||
| 97 | if (Mix.options.extractVueStyles) { |
||
| 98 | var vueExtractTextPlugin = Mix.vueExtractTextPlugin(); |
||
| 99 | |||
| 100 | plugins.push(vueExtractTextPlugin); |
||
| 101 | } |
||
| 102 | |||
| 103 | let rules = [ |
||
| 104 | { |
||
| 105 | test: /\.vue$/, |
||
| 106 | loader: 'vue-loader', |
||
| 107 | options: { |
||
| 108 | loaders: Mix.options.extractVueStyles ? { |
||
| 109 | js: 'babel-loader' + Mix.babelConfig(), |
||
| 110 | scss: vueExtractTextPlugin.extract({ |
||
|
0 ignored issues
–
show
Bug
introduced
by
Loading history...
|
|||
| 111 | use: 'css-loader!sass-loader', |
||
| 112 | fallback: 'vue-style-loader' |
||
| 113 | }), |
||
| 114 | sass: vueExtractTextPlugin.extract({ |
||
| 115 | use: 'css-loader!sass-loader?indentedSyntax', |
||
| 116 | fallback: 'vue-style-loader' |
||
| 117 | }), |
||
| 118 | less: vueExtractTextPlugin.extract({ |
||
| 119 | use: 'css-loader!less-loader', |
||
| 120 | fallback: 'vue-style-loader' |
||
| 121 | }), |
||
| 122 | stylus: vueExtractTextPlugin.extract({ |
||
| 123 | use: 'css-loader!stylus-loader?paths[]=node_modules', |
||
| 124 | fallback: 'vue-style-loader' |
||
| 125 | }), |
||
| 126 | css: vueExtractTextPlugin.extract({ |
||
| 127 | use: 'css-loader', |
||
| 128 | fallback: 'vue-style-loader' |
||
| 129 | }) |
||
| 130 | }: { |
||
| 131 | js: 'babel-loader' + Mix.babelConfig(), |
||
| 132 | scss: 'vue-style-loader!css-loader!sass-loader', |
||
| 133 | sass: 'vue-style-loader!css-loader!sass-loader?indentedSyntax', |
||
| 134 | less: 'vue-style-loader!css-loader!less-loader', |
||
| 135 | stylus: 'vue-style-loader!css-loader!stylus-loader?paths[]=node_modules' |
||
| 136 | }, |
||
| 137 | |||
| 138 | postcss: Mix.options.postCss, |
||
| 139 | |||
| 140 | preLoaders: Mix.options.vue.preLoaders, |
||
| 141 | |||
| 142 | postLoaders: Mix.options.vue.postLoaders |
||
| 143 | } |
||
| 144 | }, |
||
| 145 | |||
| 146 | { |
||
| 147 | test: /\.jsx?$/, |
||
| 148 | exclude: /(node_modules|bower_components)/, |
||
| 149 | loader: 'babel-loader' + Mix.babelConfig() |
||
| 150 | }, |
||
| 151 | |||
| 152 | { |
||
| 153 | test: /\.css$/, |
||
| 154 | loaders: ['style-loader', 'css-loader'] |
||
| 155 | }, |
||
| 156 | |||
| 157 | { |
||
| 158 | test: /\.html$/, |
||
| 159 | loaders: ['html-loader'] |
||
| 160 | }, |
||
| 161 | |||
| 162 | { |
||
| 163 | test: /\.(png|jpe?g|gif)$/, |
||
| 164 | loaders: [ |
||
| 165 | { |
||
| 166 | loader: 'file-loader', |
||
| 167 | options: { |
||
| 168 | name: path => { |
||
| 169 | if (! /node_modules|bower_components/.test(path)) { |
||
| 170 | return 'images/[name].[ext]?[hash]'; |
||
| 171 | } |
||
| 172 | |||
| 173 | return 'images/vendor/' + path |
||
| 174 | .replace(/\\/g, '/') |
||
| 175 | .replace( |
||
| 176 | /((.*(node_modules|bower_components))|images|image|img|assets)\//g, '' |
||
| 177 | ) + '?[hash]'; |
||
| 178 | }, |
||
| 179 | publicPath: Mix.options.resourceRoot |
||
| 180 | } |
||
| 181 | }, |
||
| 182 | { |
||
| 183 | loader: 'img-loader', |
||
| 184 | options: Mix.options.imgLoaderOptions |
||
| 185 | } |
||
| 186 | ] |
||
| 187 | }, |
||
| 188 | |||
| 189 | { |
||
| 190 | test: /\.(woff2?|ttf|eot|svg|otf)$/, |
||
| 191 | loader: 'file-loader', |
||
| 192 | options: { |
||
| 193 | name: path => { |
||
| 194 | if (! /node_modules|bower_components/.test(path)) { |
||
| 195 | return 'fonts/[name].[ext]?[hash]'; |
||
| 196 | } |
||
| 197 | |||
| 198 | return 'fonts/vendor/' + path |
||
| 199 | .replace(/\\/g, '/') |
||
| 200 | .replace( |
||
| 201 | /((.*(node_modules|bower_components))|fonts|font|assets)\//g, '' |
||
| 202 | ) + '?[hash]'; |
||
| 203 | }, |
||
| 204 | publicPath: Mix.options.resourceRoot |
||
| 205 | } |
||
| 206 | }, |
||
| 207 | |||
| 208 | { |
||
| 209 | test: /\.(cur|ani)$/, |
||
| 210 | loader: 'file-loader', |
||
| 211 | options: { |
||
| 212 | name: '[name].[ext]?[hash]', |
||
| 213 | publicPath: Mix.options.resourceRoot |
||
| 214 | } |
||
| 215 | } |
||
| 216 | ]; |
||
| 217 | |||
| 218 | let extensions = ['*', '.js', '.jsx', '.vue']; |
||
| 219 | |||
| 220 | if (Mix.ts) { |
||
| 221 | rules.push({ |
||
| 222 | test: /\.tsx?$/, |
||
| 223 | loader: 'ts-loader', |
||
| 224 | exclude: /node_modules/, |
||
| 225 | }); |
||
| 226 | |||
| 227 | extensions.push('.ts', '.tsx'); |
||
| 228 | } |
||
| 229 | |||
| 230 | let sassRule = { |
||
| 231 | test: /\.s[ac]ss$/, |
||
| 232 | loaders: ['style-loader', 'css-loader', 'sass-loader'] |
||
| 233 | }; |
||
| 234 | |||
| 235 | if (Mix.preprocessors) { |
||
| 236 | sassRule.exclude = Mix.preprocessors.map(preprocessor => preprocessor.test()); |
||
| 237 | } |
||
| 238 | |||
| 239 | rules.push(sassRule); |
||
| 240 | |||
| 241 | if (Mix.preprocessors) { |
||
| 242 | Mix.preprocessors.forEach(preprocessor => { |
||
| 243 | rules.push(preprocessor.rules()); |
||
| 244 | |||
| 245 | plugins.push(preprocessor.extractPlugin); |
||
| 246 | }); |
||
| 247 | } |
||
| 248 | |||
| 249 | module.exports.module = { rules }; |
||
| 250 | |||
| 251 | |||
| 252 | |||
| 253 | /* |
||
| 254 | |-------------------------------------------------------------------------- |
||
| 255 | | Resolve |
||
| 256 | |-------------------------------------------------------------------------- |
||
| 257 | | |
||
| 258 | | Here, we may set any options/aliases that affect Webpack's resolving |
||
| 259 | | of modules. To begin, we will provide the necessary Vue alias to |
||
| 260 | | load the Vue common library. You may delete this, if needed. |
||
| 261 | | |
||
| 262 | */ |
||
| 263 | |||
| 264 | module.exports.resolve = { |
||
| 265 | extensions, |
||
| 266 | |||
| 267 | alias: { |
||
| 268 | 'vue$': 'vue/dist/vue.common.js' |
||
| 269 | } |
||
| 270 | }; |
||
| 271 | |||
| 272 | |||
| 273 | |||
| 274 | /* |
||
| 275 | |-------------------------------------------------------------------------- |
||
| 276 | | Stats |
||
| 277 | |-------------------------------------------------------------------------- |
||
| 278 | | |
||
| 279 | | By default, Webpack spits a lot of information out to the terminal, |
||
| 280 | | each you time you compile. Let's keep things a bit more minimal |
||
| 281 | | and hide a few of those bits and pieces. Adjust as you wish. |
||
| 282 | | |
||
| 283 | */ |
||
| 284 | |||
| 285 | module.exports.stats = { |
||
| 286 | hash: false, |
||
| 287 | version: false, |
||
| 288 | timings: false, |
||
| 289 | children: false, |
||
| 290 | errors: false |
||
| 291 | }; |
||
| 292 | |||
| 293 | process.noDeprecation = true; |
||
| 294 | |||
| 295 | module.exports.performance = { hints: false }; |
||
| 296 | |||
| 297 | |||
| 298 | |||
| 299 | /* |
||
| 300 | |-------------------------------------------------------------------------- |
||
| 301 | | Devtool |
||
| 302 | |-------------------------------------------------------------------------- |
||
| 303 | | |
||
| 304 | | Sourcemaps allow us to access our original source code within the |
||
| 305 | | browser, even if we're serving a bundled script or stylesheet. |
||
| 306 | | You may activate sourcemaps, by adding Mix.sourceMaps(). |
||
| 307 | | |
||
| 308 | */ |
||
| 309 | |||
| 310 | module.exports.devtool = Mix.options.sourcemaps; |
||
| 311 | |||
| 312 | |||
| 313 | |||
| 314 | /* |
||
| 315 | |-------------------------------------------------------------------------- |
||
| 316 | | Webpack Dev Server Configuration |
||
| 317 | |-------------------------------------------------------------------------- |
||
| 318 | | |
||
| 319 | | If you want to use that flashy hot module replacement feature, then |
||
| 320 | | we've got you covered. Here, we'll set some basic initial config |
||
| 321 | | for the Node server. You very likely won't want to edit this. |
||
| 322 | | |
||
| 323 | */ |
||
| 324 | module.exports.devServer = { |
||
| 325 | headers: { |
||
| 326 | "Access-Control-Allow-Origin": "*" |
||
| 327 | }, |
||
| 328 | historyApiFallback: true, |
||
| 329 | noInfo: true, |
||
| 330 | compress: true, |
||
| 331 | quiet: true |
||
| 332 | }; |
||
| 333 | |||
| 334 | |||
| 335 | |||
| 336 | /* |
||
| 337 | |-------------------------------------------------------------------------- |
||
| 338 | | Plugins |
||
| 339 | |-------------------------------------------------------------------------- |
||
| 340 | | |
||
| 341 | | Lastly, we'll register a number of plugins to extend and configure |
||
| 342 | | Webpack. To get you started, we've included a handful of useful |
||
| 343 | | extensions, for versioning, OS notifications, and much more. |
||
| 344 | | |
||
| 345 | */ |
||
| 346 | |||
| 347 | plugins.push( |
||
| 348 | new webpack.ProvidePlugin(Mix.autoload || {}), |
||
| 349 | |||
| 350 | new webpackPlugins.FriendlyErrorsWebpackPlugin({ clearConsole: Mix.options.clearConsole }), |
||
| 351 | |||
| 352 | new webpackPlugins.StatsWriterPlugin({ |
||
| 353 | filename: 'mix-manifest.json', |
||
| 354 | transform: Mix.manifest.transform.bind(Mix.manifest), |
||
| 355 | }), |
||
| 356 | |||
| 357 | new webpack.LoaderOptionsPlugin({ |
||
| 358 | minimize: Mix.inProduction, |
||
| 359 | options: { |
||
| 360 | postcss: Mix.options.postCss, |
||
| 361 | context: __dirname, |
||
| 362 | output: { path: './' } |
||
| 363 | } |
||
| 364 | }) |
||
| 365 | ); |
||
| 366 | |||
| 367 | if (Mix.browserSync) { |
||
| 368 | plugins.push( |
||
| 369 | new webpackPlugins.BrowserSyncPlugin( |
||
| 370 | Object.assign({ |
||
| 371 | host: 'localhost', |
||
| 372 | port: 3000, |
||
| 373 | proxy: 'app.dev', |
||
| 374 | files: [ |
||
| 375 | 'app/**/*.php', |
||
| 376 | 'resources/views/**/*.php', |
||
| 377 | 'public/js/**/*.js', |
||
| 378 | 'public/css/**/*.css' |
||
| 379 | ] |
||
| 380 | }, Mix.browserSync), |
||
| 381 | { |
||
| 382 | reload: false |
||
| 383 | } |
||
| 384 | ) |
||
| 385 | ); |
||
| 386 | } |
||
| 387 | |||
| 388 | if (Mix.options.notifications) { |
||
| 389 | plugins.push( |
||
| 390 | new webpackPlugins.WebpackNotifierPlugin({ |
||
| 391 | title: 'Laravel Mix', |
||
| 392 | alwaysNotify: true, |
||
| 393 | contentImage: Mix.Paths.root('node_modules/laravel-mix/icons/laravel.png') |
||
| 394 | }) |
||
| 395 | ); |
||
| 396 | } |
||
| 397 | |||
| 398 | if (Mix.copy.length) { |
||
| 399 | new webpackPlugins.CopyWebpackPlugin(Mix.copy); |
||
|
0 ignored issues
–
show
|
|||
| 400 | } |
||
| 401 | |||
| 402 | if (Mix.entry().hasExtractions()) { |
||
| 403 | plugins.push( |
||
| 404 | new webpack.optimize.CommonsChunkPlugin({ |
||
| 405 | names: Mix.entry().getExtractions(), |
||
| 406 | minChunks: Infinity |
||
| 407 | }) |
||
| 408 | ); |
||
| 409 | } |
||
| 410 | |||
| 411 | if (Mix.options.versioning) { |
||
| 412 | plugins.push( |
||
| 413 | new webpack[Mix.inProduction ? 'HashedModuleIdsPlugin': 'NamedModulesPlugin'](), |
||
| 414 | new webpackPlugins.WebpackChunkHashPlugin() |
||
| 415 | ); |
||
| 416 | } else if (Mix.options.hmr) { |
||
| 417 | plugins.push( |
||
| 418 | new webpack.NamedModulesPlugin() |
||
| 419 | ); |
||
| 420 | } |
||
| 421 | |||
| 422 | if (Mix.options.purifyCss) { |
||
| 423 | let PurifyCSSPlugin = require('purifycss-webpack'); |
||
| 424 | |||
| 425 | // By default, we'll scan all Blade and Vue files in our project. |
||
| 426 | let paths = glob.sync(Mix.Paths.root('resources/views/**/*.blade.php')).concat( |
||
| 427 | Mix.entry().scripts.reduce((carry, js) => { |
||
| 428 | return carry.concat(glob.sync(js.base + '/**/*.vue')); |
||
| 429 | }, []) |
||
| 430 | ); |
||
| 431 | |||
| 432 | plugins.push(new PurifyCSSPlugin( |
||
| 433 | Object.assign({ paths }, Mix.options.purifyCss, { minimize: Mix.inProduction }) |
||
| 434 | )); |
||
| 435 | } |
||
| 436 | |||
| 437 | if (Mix.inProduction && Mix.options.uglify) { |
||
| 438 | plugins.push( |
||
| 439 | new webpack.optimize.UglifyJsPlugin(Mix.options.uglify) |
||
| 440 | ); |
||
| 441 | } |
||
| 442 | |||
| 443 | plugins.push( |
||
| 444 | new webpack.DefinePlugin( |
||
| 445 | Mix.definitions({ |
||
| 446 | NODE_ENV: Mix.inProduction |
||
| 447 | ? 'production' |
||
| 448 | : ( process.env.NODE_ENV || 'development' ) |
||
| 449 | }) |
||
| 450 | ), |
||
| 451 | |||
| 452 | new webpackPlugins.WebpackOnBuildPlugin( |
||
| 453 | stats => global.events.fire('build', stats) |
||
| 454 | ) |
||
| 455 | ); |
||
| 456 | |||
| 457 | if (! Mix.entry().hasScripts()) { |
||
| 458 | plugins.push(new webpackPlugins.MockEntryPlugin(Mix.output().path)); |
||
| 459 | } |
||
| 460 | |||
| 461 | module.exports.plugins = plugins; |
||
| 462 | |||
| 463 | |||
| 464 | |||
| 465 | /* |
||
| 466 | |-------------------------------------------------------------------------- |
||
| 467 | | Mix Finalizing |
||
| 468 | |-------------------------------------------------------------------------- |
||
| 469 | | |
||
| 470 | | Now that we've declared the entirety of our Webpack configuration, the |
||
| 471 | | final step is to scan for any custom configuration in the Mix file. |
||
| 472 | | If mix.webpackConfig() is called, we'll merge it in, and build! |
||
| 473 | | |
||
| 474 | */ |
||
| 475 | |||
| 476 | if (Mix.webpackConfig) { |
||
| 477 | module.exports = require('webpack-merge').smart( |
||
| 478 | module.exports, Mix.webpackConfig |
||
| 479 | ); |
||
| 480 | } |
||
| 481 |