New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Enable extension of webpack config by consumers #87
Changes from 1 commit
652cf60
f333363
72ee97a
628f400
c1b1ba9
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -188,7 +188,28 @@ module.exports = React.createClass({ | |
}) | ||
``` | ||
|
||
### How to write your own loaders/wrappers | ||
### How to use your own loaders | ||
|
||
Create a `gatsby.config.js` in the root of your | ||
project. `gatsby.config.js` exports a function which accepts a config | ||
object and an environment string. The environment string will be one | ||
of `serve`, `static` or `production`. | ||
|
||
Consider the following example which removes the default css loader | ||
and replaces it with a loader that uses css-modules. | ||
|
||
```javascript | ||
modules.exports = function(config, env) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. You'll probably want to introduce this by explaining we're using webpack-configurator so they can go there to learn more about what options are available.. |
||
config.removeLoader('css'); | ||
config.loader('css', function(cfg) { | ||
cfg.test = /\.css$/; | ||
cfg.loader = 'style!css?modules' | ||
return cfg | ||
}) | ||
}); | ||
``` | ||
|
||
### How to write your own wrappers | ||
* Coming... | ||
|
||
### Structure of a Gatsby site | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,11 +1,13 @@ | ||
webpack = require 'webpack' | ||
webpackConfig = require './webpack.config' | ||
path = require 'path' | ||
|
||
module.exports = (program, callback) -> | ||
{relativeDirectory, directory} = program | ||
|
||
#### Build production js. | ||
compilerConfig = webpackConfig(program, directory, 'production') | ||
webpack(compilerConfig).run (err, stats) -> | ||
config = require(path.resolve(process.cwd(), './gatsby.config.js'))(compilerConfig, 'production'); | ||
webpack(config.resolve()).run (err, stats) -> | ||
callback err, stats | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,197 @@ | ||
var webpack = require('webpack'); | ||
var StaticSiteGeneratorPlugin = require('static-site-generator-webpack-plugin'); | ||
var Config = require('webpack-configurator'); | ||
|
||
var gatsbyLib = /(gatsby.lib)/i; | ||
var libDirs = /(node_modules|bower_components)/i; | ||
var babelExcludeTest = function(absPath) { | ||
var result = false; | ||
if(absPath.match(gatsbyLib)) { | ||
// There is a match, don't exclude this file. | ||
result = false | ||
} else if(absPath.match(libDirs)) { | ||
// There is a match, do exclude this file. | ||
result = true | ||
} else { | ||
result = false | ||
} | ||
|
||
return result | ||
} | ||
|
||
module.exports = function(program, directory, stage, webpackPort, routes) { | ||
webpackPort = webpackPort || 1500; | ||
routes = routes || []; | ||
function output() { | ||
switch(stage) { | ||
case "develop": | ||
return { | ||
path: directory, | ||
filename: 'bundle.js', | ||
publicPath: `http://${program.host}:${webpackPort}/` | ||
} | ||
case "production": | ||
return { | ||
filename: "bundle.js", | ||
path: directory + "/public" | ||
} | ||
case "static": | ||
return { | ||
path: directory + "/public", | ||
filename: "bundle.js", | ||
libraryTarget: 'umd' | ||
} | ||
} | ||
} | ||
|
||
function entry() { | ||
switch(stage) { | ||
case "develop": | ||
return [ | ||
`${__dirname}/../../node_modules/webpack-dev-server/client?${program.host}:${webpackPort}`, | ||
`${__dirname}/../../node_modules/webpack/hot/only-dev-server`, | ||
`${__dirname}/web-entry` | ||
] | ||
case "production": | ||
return [ | ||
`${__dirname}/web-entry` | ||
] | ||
case "static": | ||
return [ | ||
`${__dirname}/static-entry` | ||
] | ||
} | ||
} | ||
|
||
function plugins() { | ||
switch(stage) { | ||
case "develop": | ||
return [ | ||
new webpack.HotModuleReplacementPlugin(), | ||
new webpack.DefinePlugin({ | ||
"process.env": { | ||
NODE_ENV: JSON.stringify(process.env.NODE_ENV ? process.env.NODE_ENV : "development") | ||
}, | ||
__PREFIX_LINKS__: program.prefixLinks | ||
}) | ||
] | ||
case "production": | ||
return [ | ||
new webpack.IgnorePlugin(/^\.\/locale$/, /moment$/), | ||
new webpack.DefinePlugin({ | ||
"process.env": { | ||
NODE_ENV: JSON.stringify(process.env.NODE_ENV ? process.env.NODE_ENV : "production") | ||
}, | ||
__PREFIX_LINKS__: program.prefixLinks | ||
}), | ||
new webpack.optimize.DedupePlugin(), | ||
new webpack.optimize.UglifyJsPlugin() | ||
] | ||
case "static": | ||
return [ | ||
new StaticSiteGeneratorPlugin('bundle.js', routes), | ||
new webpack.DefinePlugin({ | ||
"process.env": { | ||
NODE_ENV: JSON.stringify(process.env.NODE_ENV ? process.env.NODE_ENV : "production") | ||
}, | ||
__PREFIX_LINKS__: program.prefixLinks | ||
}) | ||
] | ||
} | ||
} | ||
|
||
function resolve() { | ||
return { | ||
extensions: ['', '.js', '.jsx', '.cjsx', '.coffee', '.json', '.less', '.toml', '.yaml'], | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Does webpack-configurator make it easy to modify extensions? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. the object wayUsing an object in
the function wayUsing a function yields more control, but when I tried it it threw up on glob-pages later in the build process. That said, it did work and in the following example, it added
Also, I think I've tracked down the issue in webpack configurator for the function-based merging. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. PR for the fix is here: lewie9021/webpack-configurator#10 There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 👍 |
||
modulesDirectories: [ | ||
directory, | ||
`${__dirname}/../isomorphic`, | ||
`${directory}/node_modules`, | ||
"node_modules" | ||
] | ||
} | ||
} | ||
|
||
function devtool() { | ||
switch(stage) { | ||
case "develop": | ||
case "static": | ||
return "eval" | ||
case "production": | ||
return "source-map" | ||
} | ||
} | ||
|
||
function module(config) { | ||
|
||
// common config for every env | ||
config.loader('cjsx',{ test: /\.cjsx$/, loaders: ['coffee', 'cjsx']}); | ||
config.loader('js',{ | ||
test: /\.jsx?$/, | ||
exclude: babelExcludeTest, | ||
loaders: ['babel'] | ||
}); | ||
config.loader('coffee',{ test: /\.coffee$/, loader: 'coffee' }); | ||
config.loader('md',{ test: /\.md$/, loader: 'markdown' }); | ||
config.loader('html',{ test: /\.html$/, loader: 'raw' }); | ||
config.loader('json',{ test: /\.json$/, loaders: ['json'] }); | ||
config.loader('toml',{ test: /^((?!config).)*\.toml$/, loaders: ['toml'] }); // Match everything except config.toml | ||
config.loader('png',{ test: /\.png$/, loader: 'null' }); | ||
config.loader('jpg',{ test: /\.jpg$/, loader: 'null' }); | ||
config.loader('svg',{ test: /\.svg$/, loader: 'null' }); | ||
config.loader('ico',{ test: /\.ico$/, loader: 'null' }); | ||
config.loader('pdf',{ test: /\.pdf$/, loader: 'null' }); | ||
config.loader('txt',{ test: /\.txt$/, loader: 'null' }); | ||
config.loader('config',{ test: /config\.[toml|yaml|json]/, loader: 'config', query: { | ||
directory: directory | ||
} }); | ||
|
||
switch(stage) { | ||
case "develop": | ||
config.loader('css', { test: /\.css$/, loaders: ['style', 'css']}); | ||
config.loader('less', { test: /\.less/, loaders: ['style', 'css', 'less']}); | ||
config.loader('js', {}, (cfg) => { | ||
console.log('cfg',cfg); | ||
cfg.loaders.unshift('react-hot'); | ||
console.log(cfg) | ||
return cfg; | ||
}) | ||
return config; | ||
|
||
case "static": | ||
config.loader('css',{ test: /\.css$/, loaders: ['css']}); | ||
config.loader('less',{ test: /\.less/, loaders: ['css', 'less']}); | ||
return config | ||
|
||
case "production": | ||
config.loader('css',{ test: /\.css$/, loaders: ['style', 'css']}); | ||
config.loader('less',{ test: /\.less/, loaders: ['style', 'css', 'less']}); | ||
|
||
return config | ||
} | ||
} | ||
var config = new Config(); | ||
|
||
console.log('loaders stage:', stage); | ||
config.merge({ | ||
context: directory + "/pages", | ||
node: { | ||
__filename: true | ||
}, | ||
entry: entry(), | ||
debug: true, | ||
devtool: devtool(), | ||
output: output(), | ||
resolveLoader: { | ||
modulesDirectories: [ | ||
`${directory}/node_modules`, | ||
`${__dirname}/../../node_modules`, | ||
`${__dirname}/../loaders` | ||
] | ||
}, | ||
plugins: plugins(), | ||
resolve: resolve() | ||
}); | ||
|
||
return module(config); | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should be develop now. Plus we should point them to the default loaders somehow so they know what they're modifying.