-
Notifications
You must be signed in to change notification settings - Fork 1.5k
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
[WIP] Move webpack config to node package #264
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
Cleanup node package and remove copying loaders Change package name Rename package Add webpack dev server Add webpack-dev-server Add missing deps Fix start and build scripts Cleanup Bump version Add utils Setup gem for dev server in hot mode Add dev server helper class Copy scripts to package.json Fix typo Remove enabled flag Bump version Move dev server option to config and use util helper to add entry points Bump version Serve from root Fix minor typo Minor update to binstubs Use block to handle failures Fix typo Set default hot server to true Remove extraneous deps Minor updates Order options Bump version Fix typo Fix typo Fix more typos Fix asset_host Don't pass env USe quotes Oops add exec Cleanup and nitpicking Bump version Fix minor typo Bump version Fix minor typo Bump version Exclude javascript package Remove .js suffix Fix config file name Fix bug Fix bug and bump version Fix linter Upgrade packages Enable toggling for sass and postcss Add a basic readme Bump version Allow env specific override Bump version Remove custom config option Fix typo Minor typos Lets use hash in all environments Use hash Don't use hash in development Don't use hash in development Remove coffee script related deps Refactor merging app level config and move coffee to it's own installer Bump version Add support for react 15.5.0 Upgrade deps Add table of contents and support stdin Bump version Tag console log with webpacker Bump version Fix colour Change color to blue Minor refactor Bump version Fix typo Start working on readme Update binstubs Spawn webpack dev server using after_initialize hook Update readme Update readme Revert railtie change Merge app config to built-in config Minor refactor around custom webpack config Update readme Bump version Update syntax Minor improvements Update readme Fix a bug related to relative url Fix typo
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
node_modules/* |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,146 @@ | ||
<!-- START doctoc generated TOC please keep comment here to allow auto update --> | ||
<!-- DON'T EDIT THIS SECTION, INSTEAD RE-RUN doctoc TO UPDATE --> | ||
**Table of Contents** *generated with [DocToc](https://github.com/thlorenz/doctoc)* | ||
|
||
`webpacker-scripts` allows you to use webpack 2 with zero build configuration. | ||
|
||
- [Webpacker Scripts](#webpacker-scripts) | ||
- [Prerequisites](#prerequisites) | ||
- [Features](#features) | ||
- [Usage with Webpacker and Rails](#usage-with-webpacker-and-rails) | ||
- [Standalone usage](#standalone-usage) | ||
- [Scripts](#scripts) | ||
- [Configuration](#configuration) | ||
- [Advanced Configuration](#advanced-configuration) | ||
- [License](#license) | ||
|
||
<!-- END doctoc generated TOC please keep comment here to allow auto update --> | ||
|
||
# Webpacker Scripts | ||
 | ||
[](https://nodejs.org/en/) | ||
[](https://github.com/rails/webpacker) | ||
|
||
Webpacker Scripts is a collection of opinionated node scripts and webpack config files built | ||
exclusively for new [Webpacker](https://github.com/rails/webpacker) gem, however, it is possible to use | ||
it as a standalone package with some extra setup. | ||
|
||
## Prerequisites | ||
|
||
* Node.js 6.4.0+ | ||
* Yarn | ||
* Webpacker gem | ||
|
||
## Features | ||
|
||
* [Webpack 2](https://webpack.js.org/) Ready | ||
* [HMR](https://webpack.js.org/concepts/hot-module-replacement/) Ready | ||
* [Webpack Dev Server](https://webpack.js.org/configuration/dev-server/) | ||
* Code splitting using multiple entry points | ||
* Stylesheet Ready with support for HMR and CSS modules | ||
* PostCSS Ready | ||
* Asset compression and minification | ||
* React, Angular and Vue support out-of-the-box | ||
* Extensible | ||
|
||
## Usage with Webpacker and Rails | ||
|
||
Webpacker Scripts comes bundled by default with the new webpacker gem, which means that | ||
whenever you run `bundle exec rails webpacker:install` it will install `webpacker-scripts` package for you, however, you can also manually add it by running `yarn add webpacker-scripts` | ||
in an existing Rails project. | ||
|
||
## Standalone usage | ||
|
||
Webpacker Scripts is built exclusively for new Webpacker gem, but since this is just | ||
standard node package you can use it in any other project with some extra setup. | ||
|
||
The extra step required | ||
for you to copy the webpacker config files from the gem repo to your project in same | ||
structure i.e. `config/webpack/[*.yml]`. You might also wanna copy the `.postcssrc.yml` and | ||
`.babelrc` to your project root for postcss and babel to compile files properly. | ||
|
||
## Scripts | ||
|
||
Webpacker Scripts comes with two tasks -`build` and `start`, which can be run | ||
using `webpacker` binary once installed. | ||
|
||
```bash | ||
./node_modules/.bin/webpacker start | ||
./node_modules/.bin/webpacker build | ||
``` | ||
|
||
Start tasks starts the `webpack-dev-server` in development environment, where as the build | ||
the task is designed to produce optimized production app bundle. | ||
|
||
## Configuration | ||
|
||
Webpacker Scripts references all configuration settings from `config/webpack/*.yml` files, which are pretty well documented. When you create new rails 5.1 apps with `--webpack` option or run the webpacker installer manually these files will be copied automatically for you by the installer to `config/webpack` directory. | ||
|
||
```yml | ||
# config/webpack/paths.yml | ||
source: app/javascript | ||
entry: packs | ||
output: public | ||
``` | ||
*Note:* Behind the scenes, webpacker will use same `entry` directory name inside `output` | ||
directory to emit bundles. For ex, `public/packs` | ||
|
||
Similary, you can also control and configure `webpack-dev-server` settings from | ||
`config/webpack/development.server.yml` file | ||
|
||
```yml | ||
# config/webpack/development.server.yml | ||
enabled: true | ||
host: localhost | ||
port: 8080 | ||
``` | ||
|
||
By default, `webpack-dev-server` uses `output` option specified in | ||
`paths.yml` as `contentBase`. | ||
|
||
## Advanced Configuration | ||
|
||
Webpacker Scripts allows overriding built-in webpack config files with your own configuration. All you have to do is create a `config/webpack/webpack.config.js` and export | ||
a `webpack` function that extends base webpack config. | ||
|
||
For example, lets say you want to add `react-hot-loader` entry point, you can do | ||
it like so, | ||
|
||
```js | ||
// config/webpack/webpack.config.js | ||
const merge = require('webpack-merge') | ||
module.exports = { | ||
webpack: (webpackConfig, { ifDevelopment, ifProduction, ifTest, env }) => { | ||
if (ifDevelopment()) { | ||
const reactHotClient = ['react-hot-loader/patch'] | ||
Object.keys(webpackConfig.entry).forEach((key) => { | ||
webpackConfig.entry[key] = reactHotClient.concat(webpackConfig.entry[key]); | ||
}) | ||
} | ||
// Important: return the webpackConfig | ||
return webpackConfig | ||
} | ||
} | ||
``` | ||
|
||
Similarly, you can also add your own loaders that don't come out of the box with `webpacker-scripts`, just create a `loaders` directory under `config/webpack` and export | ||
your loader module and that's it. | ||
|
||
For example, lets say you want to add the `html-loader`, you can do it like so: | ||
|
||
```js | ||
// config/webpack/loaders/html.js | ||
module.exports = { | ||
test: /\.html$/, | ||
use: [{ | ||
loader: 'html-loader', | ||
options: { | ||
minimize: true | ||
} | ||
}] | ||
} | ||
``` | ||
|
||
## License | ||
Webpacker is released under the [MIT License](https://opensource.org/licenses/MIT). |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
#!/usr/bin/env node | ||
/* eslint no-case-declarations: 0 */ | ||
|
||
const spawn = require('cross-spawn') | ||
|
||
const script = process.argv[2] | ||
const args = process.argv.slice(3) | ||
|
||
switch (script) { | ||
case 'build': | ||
case 'start': | ||
case 'test': | ||
const result = spawn.sync('node', [require.resolve(`../scripts/${script}`)].concat(args), { stdio: 'inherit' }) | ||
process.exit(result.status) | ||
break | ||
default: | ||
console.log(`Unknown script ${script}`) /* eslint no-console: 0 */ | ||
break | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,45 @@ | ||
// Common configuration for webpacker loaded from config/webpack/paths.yml | ||
|
||
const { env } = require('process') | ||
const { getIfUtils, propIf } = require('webpack-config-utils') | ||
const { join, resolve } = require('path') | ||
const { readFileSync } = require('fs') | ||
const { safeLoad } = require('js-yaml') | ||
const computeAssetUrl = require('../utils/computer-asset-url') | ||
|
||
// Define webpack configuration file path | ||
const appConfigPath = resolve(process.cwd(), 'config', 'webpack') | ||
|
||
// Setup environment utils | ||
const { ifProduction, ifDevelopment, ifTest } = getIfUtils(process.env.NODE_ENV) | ||
|
||
// Load configuration from .yml files | ||
const devServer = safeLoad(readFileSync(join(appConfigPath, 'development.server.yml'), 'utf8'))[env.NODE_ENV] | ||
const paths = safeLoad(readFileSync(join(appConfigPath, 'paths.yml'), 'utf8'))[env.NODE_ENV] | ||
const settings = safeLoad(readFileSync(join(appConfigPath, 'settings.yml'), 'utf8')) | ||
|
||
// Compute public path based on environment and CDN option | ||
const devServerUrl = `${devServer.protocol}://${devServer.host}:${devServer.port}/` | ||
const ifHasCDN = env.ASSET_HOST !== undefined && ifProduction() | ||
const publicUrl = propIf(ifHasCDN, `${computeAssetUrl(env.ASSET_HOST)}${paths.entry}/`, `/${paths.entry}/`) | ||
const publicPath = propIf(ifDevelopment(), devServerUrl, publicUrl) | ||
|
||
// Define path helpers | ||
const manifestPath = resolve(paths.output, paths.entry, paths.manifest) | ||
const outputPath = resolve(paths.output, paths.entry) | ||
|
||
// Export common configuration | ||
module.exports = { | ||
appConfigPath, | ||
devServer, | ||
env, | ||
ifDevelopment, | ||
ifProduction, | ||
ifTest, | ||
manifestPath, | ||
outputPath, | ||
paths, | ||
publicPath, | ||
publicUrl, | ||
settings | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,12 +1,12 @@ | ||
const { env, publicPath } = require('../configuration.js') | ||
const { ifProduction, publicPath } = require('../index') | ||
|
||
module.exports = { | ||
test: /\.(jpg|jpeg|png|gif|svg|eot|ttf|woff|woff2)$/i, | ||
use: [{ | ||
loader: 'file-loader', | ||
options: { | ||
publicPath, | ||
name: env.NODE_ENV === 'production' ? '[name]-[hash].[ext]' : '[name].[ext]' | ||
name: ifProduction() ? '[name]-[hash].[ext]' : '[name].[ext]' | ||
} | ||
}] | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
module.exports = { | ||
test: /\.js(\.erb)?$/, | ||
exclude: /node_modules/, | ||
loader: 'babel-loader' | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,35 @@ | ||
const ExtractTextPlugin = require('extract-text-webpack-plugin') | ||
const { removeEmpty, propIf } = require('webpack-config-utils') | ||
const { ifProduction, ifDevelopment, settings } = require('../index') | ||
|
||
const loaderOptions = { | ||
fallback: 'style-loader', | ||
use: removeEmpty([{ | ||
loader: 'css-loader', | ||
// Add optional css-modules support | ||
// Documentation https://github.com/css-modules/css-modules | ||
options: removeEmpty({ | ||
modules: settings.css_modules, | ||
minimize: ifProduction(), | ||
// Use a local class name if css modules are enabled | ||
localIdentName: propIf( | ||
settings.css_modules, | ||
'[path][name]__[local]--[hash:base64:5]', | ||
undefined | ||
) | ||
}) | ||
}, | ||
// Toggle postcss and sass support | ||
propIf(settings.postcss, 'postcss-loader', undefined), | ||
propIf(settings.sass, 'sass-loader', undefined) | ||
]) | ||
} | ||
|
||
// For development use regular loaders else use extract-text-plugin | ||
module.exports = propIf(ifDevelopment(), { | ||
test: /\.(scss|sass|css)$/i, | ||
use: ['style-loader'].concat(loaderOptions.use) | ||
}, { | ||
test: /\.(scss|sass|css)$/i, | ||
use: ExtractTextPlugin.extract(loaderOptions) | ||
}) |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
module.exports = { | ||
test: /\.(js|jsx)?(\.erb)?$/, | ||
exclude: /node_modules/, | ||
loader: 'babel-loader' | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,48 @@ | ||
// Note: You must restart bin/webpack-watcher for changes to take effect | ||
|
||
const webpack = require('webpack') | ||
const merge = require('webpack-merge') | ||
const sharedConfig = require('./shared') | ||
const { devServer, outputPath, publicPath } = require('../index') | ||
|
||
module.exports = merge(sharedConfig, { | ||
devtool: 'cheap-module-source-map', | ||
|
||
stats: { | ||
errorDetails: true | ||
}, | ||
|
||
output: { | ||
pathinfo: true | ||
}, | ||
|
||
devServer: { | ||
// Show only compile warnings and errors. | ||
clientLogLevel: 'none', | ||
compress: true, | ||
contentBase: outputPath, | ||
headers: { 'Access-Control-Allow-Origin': '*' }, | ||
historyApiFallback: true, | ||
host: devServer.host, | ||
// Optional HMR support - https://webpack.js.org/concepts/hot-module-replacement/ | ||
// Works with JS, CSS and Vue out-of-the-box | ||
// More info on integrating HMR with React: https://webpack.js.org/guides/hmr-react/ | ||
hot: devServer.hot, | ||
// Enable HTTPS if the protocol is https | ||
https: devServer.protocol === 'https', | ||
inline: true, | ||
port: devServer.port, | ||
publicPath, | ||
// Disable logs | ||
quiet: devServer.quiet, | ||
// Avoids CPU overload on some systems. | ||
watchOptions: { | ||
ignored: /node_modules/ | ||
} | ||
}, | ||
|
||
plugins: [ | ||
new webpack.HotModuleReplacementPlugin(), | ||
new webpack.NamedModulesPlugin() | ||
] | ||
}) |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,39 @@ | ||
// Note: You must run bin/webpack for changes to take effect | ||
|
||
const CompressionPlugin = require('compression-webpack-plugin') | ||
const ExtractTextPlugin = require('extract-text-webpack-plugin') | ||
const merge = require('webpack-merge') | ||
const webpack = require('webpack') | ||
const sharedConfig = require('./shared') | ||
|
||
module.exports = merge(sharedConfig, { | ||
devtool: 'source-map', | ||
stats: 'normal', | ||
output: { filename: '[name]-[chunkhash].js' }, | ||
|
||
plugins: [ | ||
new ExtractTextPlugin('[name]-[hash].css'), | ||
|
||
new webpack.optimize.UglifyJsPlugin({ | ||
minimize: true, | ||
sourceMap: true, | ||
compress: { | ||
screw_ie8: true, | ||
warnings: false | ||
}, | ||
mangle: { | ||
screw_ie8: true | ||
}, | ||
output: { | ||
comments: false, | ||
screw_ie8: true | ||
} | ||
}), | ||
|
||
new CompressionPlugin({ | ||
asset: '[path].gz[query]', | ||
algorithm: 'gzip', | ||
test: /\.(js|css|svg|eot|ttf|woff|woff2)$/ | ||
}) | ||
] | ||
}) |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,6 +1,6 @@ | ||
// Note: You must restart bin/webpack-watcher for changes to take effect | ||
|
||
const merge = require('webpack-merge') | ||
const sharedConfig = require('./shared.js') | ||
const sharedConfig = require('./shared') | ||
|
||
module.exports = merge(sharedConfig, {}) |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
// export all webpack configurations | ||
|
||
const config = require('./config') | ||
const development = require('./config/webpack/development') | ||
const production = require('./config/webpack/production') | ||
const test = require('./config/webpack/test') | ||
|
||
module.exports = { | ||
config, | ||
development, | ||
production, | ||
test | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,51 @@ | ||
{ | ||
"name": "webpacker-scripts", | ||
"version": "0.3.7", | ||
"description": "Use Webpack to manage app-like JavaScript modules in Rails", | ||
"repository": "https://github.com/rails/webpacker", | ||
"author": "David Heinemeier Hansson", | ||
"license": "MIT", | ||
"main": "index.js", | ||
"engines": { | ||
"node": ">=6.4" | ||
}, | ||
"files": [ | ||
"bin", | ||
"config", | ||
"scripts", | ||
"utils", | ||
"index.js" | ||
], | ||
"bin": { | ||
"webpacker": "./bin/webpacker.js" | ||
}, | ||
"dependencies": { | ||
"autoprefixer": "^6.7.7", | ||
"babel-core": "^6.24.1", | ||
"babel-loader": "6.4.1", | ||
"babel-preset-env": "^1.4.0", | ||
"chalk": "^1.1.3", | ||
"compression-webpack-plugin": "^0.4.0", | ||
"cross-spawn": "^5.1.0", | ||
"css-loader": "^0.28.0", | ||
"detect-port": "^1.1.1", | ||
"extract-text-webpack-plugin": "^2.1.0", | ||
"file-loader": "^0.11.1", | ||
"glob": "^7.1.1", | ||
"js-yaml": "^3.8.3", | ||
"node-sass": "^4.5.2", | ||
"path": "^0.12.7", | ||
"path-complete-extname": "^0.1.0", | ||
"postcss-loader": "^1.3.3", | ||
"postcss-smart-import": "^0.6.12", | ||
"precss": "^1.4.0", | ||
"rails-erb-loader": "^5.0.0", | ||
"sass-loader": "^6.0.3", | ||
"style-loader": "^0.16.1", | ||
"webpack": "^2.4.1", | ||
"webpack-config-utils": "^2.3.0", | ||
"webpack-dev-server": "^2.4.3", | ||
"webpack-manifest-plugin": "^1.1.0", | ||
"webpack-merge": "^4.1.0" | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,55 @@ | ||
/* eslint no-console: 0 */ | ||
/* eslint global-require: 0 */ | ||
/* eslint import/no-dynamic-require: 0 */ | ||
|
||
// Fetch NODE_ENV or setup default to production | ||
process.env.NODE_ENV = process.env.NODE_ENV || 'production' | ||
|
||
const chalk = require('chalk') | ||
const webpack = require('webpack') | ||
let webpackConfig = require('../config/webpack/production') | ||
const config = require('../config') | ||
const getConfig = require('../utils/get-config') | ||
const logErrors = require('../utils/log-errors') | ||
|
||
const appConfig = getConfig() | ||
|
||
if (appConfig.webpack) { | ||
console.log(`${chalk.blue('[webpacker]')} ${chalk.cyan('Using "webpack" config function defined in webpack.config.js.')}`) | ||
webpackConfig = appConfig.webpack(webpackConfig, config) | ||
} | ||
|
||
// Compile and build an optimised production bundle | ||
const build = () => { | ||
console.log(`${chalk.blue('[webpacker]')} ${chalk.cyan('Building an optimized production bundle...')}`) | ||
webpack(webpackConfig).run((err, stats) => { | ||
const info = stats.toJson() | ||
|
||
if (err) { | ||
logErrors('Failed to compile.', [err]) | ||
process.exit(1) | ||
} | ||
|
||
if (stats.hasWarnings()) { | ||
console.log(`${chalk.blue('[webpacker]')} ${chalk.yellow('Build with warnings.')}`) | ||
logErrors(info.warnings) | ||
} | ||
|
||
if (stats.hasErrors()) { | ||
console.log(`${chalk.blue('[webpacker]')} ${chalk.red('Failed to build.')}`) | ||
logErrors(info.errors) | ||
process.exit(1) | ||
} | ||
|
||
console.log() | ||
console.log(`${chalk.blue('[webpacker]')} ${chalk.green('Production Build succeeded 🎉')}`) | ||
console.log(`${chalk.blue('[webpacker]')} The production bundles are emitted to:`) | ||
console.log(`${chalk.blue('[webpacker]')} ${chalk.green(config.outputPath)}`) | ||
console.log() | ||
console.log(`${chalk.blue('[webpacker]')} The production bundles are:`) | ||
console.log(`${chalk.blue('[webpacker]')} ${chalk.green(JSON.stringify(require(config.manifestPath)))}`) | ||
}) | ||
} | ||
|
||
// Start the webpack build process | ||
build() |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,80 @@ | ||
/* eslint no-console: 0 */ | ||
|
||
// Fetch NODE_ENV or setup default to production | ||
process.env.NODE_ENV = process.env.NODE_ENV || 'development' | ||
|
||
const addDevServerEntrypoints = require('webpack-dev-server/lib/util/addDevServerEntrypoints') | ||
const chalk = require('chalk') | ||
const detect = require('detect-port') | ||
const Webpack = require('webpack') | ||
const WebpackDevServer = require('webpack-dev-server') | ||
let webpackConfig = require('../config/webpack/development') | ||
const config = require('../config') | ||
const getConfig = require('../utils/get-config') | ||
const logErrors = require('../utils/log-errors') | ||
|
||
const appConfig = getConfig() | ||
|
||
if (appConfig.webpack) { | ||
console.log(`${chalk.blue('[webpacker]')} ${chalk.cyan('Using "webpack" config function defined in webpack.config.js.')}`) | ||
webpackConfig = appConfig.webpack(webpackConfig, config) | ||
} | ||
|
||
// Make dev entries hot | ||
addDevServerEntrypoints(webpackConfig, webpackConfig.devServer) | ||
|
||
// Setup compiler with hot entries | ||
const compiler = Webpack(webpackConfig, (err, stats) => { | ||
const info = stats.toJson() | ||
|
||
if (err) { | ||
console.log(`${chalk.blue('[webpacker]')} ${chalk.red('Failed to compile.')}`) | ||
console.error(`${chalk.blue('[webpacker]')} ${chalk.red(err.stack || err)}`) | ||
console.log(`${chalk.blue('[webpacker]')} ${chalk.red(err.details)}`) | ||
return | ||
} | ||
|
||
if (stats.hasErrors()) { | ||
console.log(`${chalk.blue('[webpacker]')} ${chalk.red('Failed to compile.')}`) | ||
logErrors(info.errors) | ||
return | ||
} | ||
|
||
if (stats.hasWarnings()) { | ||
console.log(`${chalk.blue('[webpacker]')} ${chalk.yellow('Compiled with warnings.')}`) | ||
logErrors(info.warnings) | ||
} | ||
|
||
console.log(`${chalk.blue('[webpacker]')} ${chalk.green('Compiled successfully!')}`) | ||
console.log() | ||
console.log(`${chalk.blue('[webpacker]')} The webpack-dev-server is serving assets at:`) | ||
console.log() | ||
console.log(`${chalk.blue('[webpacker]')} ${config.publicPath}`) | ||
console.log() | ||
}) | ||
|
||
const run = () => { | ||
// Initialize webpack-dev-server with compiler and dev server options | ||
const webpackDevServer = new WebpackDevServer(compiler, webpackConfig.devServer) | ||
|
||
// Launch webpack-dev-server on configured port and host | ||
webpackDevServer.listen(config.devServer.port, (err) => { | ||
if (err) { console.log(chalk.red(err)) } | ||
console.log(`${chalk.blue('[webpacker]')} ${chalk.cyan('Starting the webpack dev server...')}`) | ||
console.log() | ||
}) | ||
} | ||
|
||
// Check port and call function to run webpack-dev-server | ||
detect(config.devServer.port).then((port) => { | ||
if (config.devServer.port === port) { | ||
run() | ||
} else { | ||
console.log(`${chalk.blue('[webpacker]')} ${chalk.red(`Another application is using port ${config.devServer.port}.`)}`) | ||
process.exit(1) | ||
} | ||
}) | ||
|
||
// Respect stdin | ||
process.stdin.resume() | ||
process.stdin.on('end', () => { process.exit(0) }) |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,55 @@ | ||
/* eslint no-console: 0 */ | ||
/* eslint global-require: 0 */ | ||
/* eslint import/no-dynamic-require: 0 */ | ||
|
||
// Fetch NODE_ENV or setup default to test | ||
process.env.NODE_ENV = process.env.NODE_ENV || 'test' | ||
|
||
const chalk = require('chalk') | ||
const webpack = require('webpack') | ||
let webpackConfig = require('../config/webpack/test') | ||
const config = require('../config') | ||
const getConfig = require('../utils/get-config') | ||
const logErrors = require('../utils/log-errors') | ||
|
||
const appConfig = getConfig() | ||
|
||
if (appConfig.webpack) { | ||
console.log(`${chalk.blue('[webpacker]')} ${chalk.cyan('Using "webpack" config function defined in webpack.config.js.')}`) | ||
webpackConfig = appConfig.webpack(webpackConfig, config) | ||
} | ||
|
||
// Compile and build a test bundle | ||
const build = () => { | ||
console.log(`${chalk.blue('[webpacker]')} ${chalk.cyan('Building a test bundle...')}`) | ||
webpack(webpackConfig).run((err, stats) => { | ||
const info = stats.toJson() | ||
|
||
if (err) { | ||
logErrors('Failed to compile.', [err]) | ||
process.exit(1) | ||
} | ||
|
||
if (stats.hasWarnings()) { | ||
console.log(`${chalk.blue('[webpacker]')} ${chalk.yellow('Compiled with warnings.')}`) | ||
logErrors(info.warnings) | ||
} | ||
|
||
if (stats.hasErrors()) { | ||
console.log(`${chalk.blue('[webpacker]')} ${chalk.red('Failed to compile.')}`) | ||
logErrors(info.errors) | ||
process.exit(1) | ||
} | ||
|
||
console.log() | ||
console.log(`${chalk.blue('[webpacker]')} ${chalk.green('Test build succeeded 🎉')}`) | ||
console.log(`${chalk.blue('[webpacker]')} The test bundles are emitted to:`) | ||
console.log(`${chalk.blue('[webpacker]')} ${chalk.green(config.outputPath)}`) | ||
console.log() | ||
console.log(`${chalk.blue('[webpacker]')} The test bundles are:`) | ||
console.log(`${chalk.blue('[webpacker]')} ${chalk.green(JSON.stringify(require(config.manifestPath)))}`) | ||
}) | ||
} | ||
|
||
// Start the webpack build process | ||
build() |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
const url = require('url') | ||
|
||
const computeAssetUrl = (host) => { | ||
if (host) { | ||
const parsedHost = url.parse(host) | ||
if (parsedHost.slashes) { return parsedHost.href } | ||
return `//${parsedHost.href.replace('//', '')}/` | ||
} | ||
|
||
return host | ||
} | ||
|
||
module.exports = computeAssetUrl |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
/* eslint global-require: 0 */ | ||
/* eslint import/no-dynamic-require: 0 */ | ||
|
||
const { join } = require('path') | ||
const { existsSync } = require('fs') | ||
const { appConfigPath } = require('../config') | ||
|
||
const cache = new Map() | ||
|
||
const loadConfig = () => { | ||
const path = join(appConfigPath, 'webpack.config.js') | ||
let appConfig = {} | ||
if (existsSync(path)) { appConfig = require(path) } | ||
|
||
return appConfig | ||
} | ||
|
||
const getConfig = () => { | ||
if (!cache.has(appConfigPath)) { cache.set(appConfigPath, loadConfig()) } | ||
return cache.get(appConfigPath) | ||
} | ||
|
||
module.exports = getConfig |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
/* eslint no-console: 0 */ | ||
const chalk = require('chalk') | ||
|
||
// Function to log errors in console | ||
const logErrors = (errors) => { | ||
errors.forEach((err) => { | ||
console.log(`${chalk.blue('[webpacker]')} ${chalk.red(err.message || err)}`) | ||
console.log() | ||
}) | ||
} | ||
|
||
module.exports = logErrors |
Large diffs are not rendered by default.
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
<%= shebang %> | ||
$stdout.sync = true | ||
|
||
require "shellwords" | ||
require "yaml" | ||
|
||
APP_PATH = File.expand_path("../", __dir__) | ||
NODE_MODULES_PATH = File.join(APP_PATH.shellescape, "node_modules") | ||
WEBPACKER_BIN = "#{NODE_MODULES_PATH}/.bin/webpacker" | ||
|
||
Dir.chdir(APP_PATH) do | ||
begin | ||
exec "#{WEBPACKER_BIN} test" | ||
rescue Errno::ENOENT | ||
puts "Webpacker executable is not installed" | ||
puts "Run yarn add webpacker-scripts or install using bundle exec rails webpacker:install" | ||
end | ||
end |
This file was deleted.
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
require "webpacker/configuration" | ||
|
||
puts "Installing coffee script dependencies" | ||
run "./bin/yarn add coffee-loader coffee-script" | ||
|
||
puts "Webpacker now supports CoffeeScript 🎉" |
This file was deleted.
This file was deleted.
This file was deleted.
This file was deleted.
This file was deleted.
This file was deleted.
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,16 +1,23 @@ | ||
# Restart webpack-dev-server if you make changes here | ||
default: &default | ||
enabled: true | ||
# Optional HMR support - https://webpack.js.org/concepts/hot-module-replacement/ | ||
# Set true if you need HMR support | ||
hot: true | ||
host: localhost | ||
protocol: http | ||
port: 8080 | ||
# Usually dev server logs a lot of noise | ||
quiet: true | ||
|
||
development: | ||
<<: *default | ||
|
||
test: | ||
<<: *default | ||
enabled: false | ||
|
||
production: | ||
<<: *default | ||
enabled: false | ||
# Useful for cloud9 | ||
host: 0.0.0.0 | ||
port: 80 | ||
protocol: https |
This file was deleted.
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
# Restart webpack-dev-server if you make changes here | ||
|
||
# Add optional css_modules support | ||
# Read doc here: https://github.com/css-modules/css-modules | ||
css_modules: false | ||
|
||
# Add optional postcss support | ||
# http://postcss.org/ | ||
postcss: true | ||
|
||
# Add optional sass support | ||
# https://github.com/webpack-contrib/sass-loader | ||
sass: true |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
{ | ||
"presets": [ | ||
["env", { "modules": false } ] | ||
] | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,15 +1,26 @@ | ||
require "webpacker/configuration" | ||
|
||
puts "Copying react loader to #{Webpacker::Configuration.config_path}/loaders" | ||
copy_file "#{__dir__}/config/loaders/installers/react.js", "config/webpack/loaders/react.js" | ||
babelrc = Rails.root.join(".babelrc") | ||
if File.exist?(babelrc) | ||
react_babelrc = JSON.parse(File.read(babelrc)) | ||
react_babelrc["presets"] ||= [] | ||
unless react_babelrc["presets"].include?("react") | ||
react_babelrc["presets"].push("react") | ||
puts "Copying react preset to your .babelrc file" | ||
|
||
puts "Copying .babelrc to app root directory" | ||
copy_file "#{__dir__}/examples/react/.babelrc", ".babelrc" | ||
File.open(babelrc, "w") do |f| | ||
f.puts JSON.pretty_generate(react_babelrc) | ||
end | ||
end | ||
else | ||
puts "Copying .babelrc to app root directory" | ||
copy_file "#{__dir__}/examples/react/.babelrc", ".babelrc" | ||
end | ||
|
||
puts "Copying react example entry file to #{Webpacker::Configuration.entry_path}" | ||
copy_file "#{__dir__}/examples/react/hello_react.jsx", "#{Webpacker::Configuration.entry_path}/hello_react.jsx" | ||
|
||
puts "Installing all react dependencies" | ||
run "./bin/yarn add react react-dom babel-preset-react" | ||
run "./bin/yarn add react react-dom babel-preset-react prop-types" | ||
|
||
puts "Webpacker now supports react.js 🎉" |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,31 +1,26 @@ | ||
# Install webpacker | ||
puts "Copying webpack configuration files" | ||
directory "#{__dir__}/config/webpack", "config/webpack" | ||
|
||
puts "Creating javascript app source directory" | ||
directory "#{__dir__}/javascript", "app/javascript" | ||
directory "#{__dir__}/javascript", "#{Webpacker::Configuration.source}" | ||
|
||
puts "Copying binstubs" | ||
directory "#{__dir__}/bin", "bin" | ||
chmod "bin", 0755 & ~File.umask, verbose: false | ||
|
||
puts "Copying webpack core config and loaders" | ||
directory "#{__dir__}/config/webpack", "config/webpack" | ||
directory "#{__dir__}/config/loaders/core", "config/webpack/loaders" | ||
puts "Copying babel and postcss config" | ||
copy_file "#{__dir__}/examples/javascript/.babelrc", ".babelrc" | ||
copy_file "#{__dir__}/config/.postcssrc.yml", ".postcssrc.yml" | ||
|
||
if File.exists?(".gitignore") | ||
puts "Updating .gitignore" | ||
append_to_file ".gitignore", <<-EOS | ||
/public/packs | ||
/node_modules | ||
EOS | ||
end | ||
|
||
puts "Installing all JavaScript dependencies" | ||
run "./bin/yarn add webpack webpack-merge js-yaml path-complete-extname " \ | ||
"webpack-manifest-plugin babel-loader coffee-loader coffee-script " \ | ||
"babel-core babel-preset-env compression-webpack-plugin rails-erb-loader glob " \ | ||
"extract-text-webpack-plugin node-sass file-loader sass-loader css-loader style-loader " \ | ||
"postcss-loader autoprefixer postcss-smart-import precss" | ||
|
||
puts "Installing dev server for live reloading" | ||
run "./bin/yarn add --dev webpack-dev-server" | ||
|
||
puts "Installing webpacker-scripts" | ||
run "./bin/yarn add webpacker-scripts" | ||
puts "Webpacker successfully installed 🎉 🍰" |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,5 +1,6 @@ | ||
INSTALLERS = { | ||
"Angular": :angular, | ||
"Coffee": :coffee, | ||
"React": :react, | ||
"Vue": :vue | ||
}.freeze | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
# Loads webpacker configuration from config/webpack/development.server.yml | ||
require "webpacker/file_loader" | ||
require "webpacker/env" | ||
|
||
class Webpacker::DevServer < Webpacker::FileLoader | ||
class << self | ||
def file_path | ||
Rails.root.join("config", "webpack", "development.server.yml") | ||
end | ||
|
||
def settings | ||
load if Webpacker::Env.development? | ||
raise Webpacker::FileLoader::FileLoaderError.new("Webpacker::Configuration.DevServer must be called first") unless instance | ||
instance.data | ||
end | ||
|
||
def hot? | ||
Webpacker::Env.development? && settings.fetch(:hot, true) | ||
end | ||
end | ||
|
||
private | ||
def load | ||
return super unless File.exist?(@path) | ||
HashWithIndifferentAccess.new(YAML.load(File.read(@path))[Webpacker::Env.current]) | ||
end | ||
end |
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.
Installing a .babelrc by default seems like a good idea to me, but it does mean that an enthusiastic user that tries to install React through Webpacker afterwards will get a conflict on it. Maybe we can improve the installation of React by not trying to replace the .babelrc but try to add the react preset to it?
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.
Yepp, that's the plan 👍 I will fix :)