makestatic-pack-webpack
Version:
Bundle assets using webpack
202 lines (174 loc) • 4.95 kB
JavaScript
const path = require('path')
const entry = './js/index.js'
const shortcuts = ['script', 'markup', 'styles']
const standardKeys = [
'url',
'input',
'output',
'ignore',
'matchers',
'lifecycle',
'server',
'static',
'test',
'manifest',
'gzip',
'deploy',
'clean',
'provider'
].concat(shortcuts)
/**
* Converts the build configuration into a webpack compatible configuration
* removing fields that are not used by webpack.
*
* @class Config
*/
class Config {
/**
* Creates a Config.
*
* @constructor Config
* @param {Object} context the processing context.
*/
constructor (context) {
this.context = context
}
/**
* Get a webpack compatible configuration.
*
* @function getConfig
* @member Config
* @param {Object} system plugins required by the system.
* @param {Object} options plugin options.
*/
getConfig (system = {}, options = {}) {
const log = this.context.log
const opts = this.context.options
const plugins = system.plugins
// complex instances are mangled in the merge
delete system.plugins
shortcuts.forEach((k) => {
if (typeof opts[k] === 'function') {
opts[k] = opts[k](this.context)
}
})
let conf = Object.assign({}, this.context.config.raw)
this.removeKeys(conf, standardKeys)
const test = options.test || conf.test || require('./test')
conf.plugins = conf.plugins || []
// plugins passed in the system take precedence
// options specific to the plugin configuration are added afterwards
conf.plugins = plugins.concat(conf.plugins)
if (!conf.entry) {
conf.entry = {
'js/main.js': [entry]
}
}
conf.context = this.context.options.root
conf.output = {
path: opts.output,
filename: '[name]'
}
//console.dir(opts.output)
//process.exit(1)
if (this.context.options.watch) {
const BrowserSyncPlugin = require('browser-sync-webpack-plugin')
const bsopts = this.context.options.server
bsopts.server = bsopts.server || {}
bsopts.server.baseDir = [this.context.options.output]
const sync = this.context.options.sync
/* istanbul ignore next: not going to mock snippet request */
bsopts.snippetOptions = {
rule: {
match: /<\/body>/i,
fn: (snippet, match) => {
// NOTE: when sync is false we disable injecting the browsersync
// NOTE: snippet which means that browsersync is just a static
// NOTE: file server
if (sync === false) {
return match
}
// browsersync uses document.write() which messes with CSP
// so let's just used a plain script otherwise we
// need to add `script-src 'unsafe-inline'` which is not cool
const version = require('browser-sync/package.json').version
const script = `<script defer ` +
`src="/browser-sync/browser-sync-client.js?v=${version}"></script>`
return script + match
}
}
}
const bs = new BrowserSyncPlugin(
bsopts, { callback: (_, bs) => {
// don't know a better way to get actual port in use yet
const port = bs.server._connectionKey.replace(/^[^:]+:+/, '')
log.info(
`External IP: http://${bs.utils.devIp[0]}:${port}`)
}}
)
conf.plugins.push(bs)
}
conf.module = options.module || conf.module || {
rules: [
{
test: test.vendor,
use: [
{ loader: 'source-loader' }
]
},
{
test: test.css,
use: [
{ loader: 'source-loader' },
{ loader: 'postcss-loader', options: opts.styles }
]
},
{
test: test.js,
use: [
{ loader: 'babel-loader', options: opts.script }
]
},
{
test: test.html,
use: [
{ loader: 'source-loader' },
{ loader: 'reshape-loader', options: opts.markup }
]
},
{
test: /\.json$/,
use: [
{ loader: 'source-loader' }
]
},
{
test: test.static,
loader: 'source-loader'
}
]
}
conf.resolve = options.resolve || conf.resolve || {
extensions: ['.js', '.jsx'],
descriptionFiles: []
}
conf.resolveLoader = options.resolveLoader || conf.resolveLoader || {
modules: [
path.join(process.cwd(), 'node_modules')
// NOTE: this slows things down dramatically
// path.join(__dirname, 'node_modules')
]
}
return conf
}
/**
* Remove keys from an object.
*/
removeKeys (conf, keys) {
keys.forEach((k) => {
delete conf[k]
})
return conf
}
}
module.exports = Config