Skip to content

Commit 50aaf77

Browse files
authored
Merge pull request #706 from rails/node-module
Node module
2 parents d1ff620 + 2146503 commit 50aaf77

33 files changed

+5075
-1010
lines changed

README.md

Lines changed: 67 additions & 171 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
[![Gem](https://img.shields.io/gem/v/webpacker.svg)](https://github.com/rails/webpacker)
66

77
Webpacker makes it easy to use the JavaScript pre-processor and bundler
8-
[Webpack 2.x.x+](https://webpack.js.org/)
8+
[Webpack 3.x.x+](https://webpack.js.org/)
99
to manage application-like JavaScript in Rails. It coexists with the asset pipeline,
1010
as the primary purpose for Webpack is app-like JavaScript, not images, CSS, or
1111
even JavaScript Sprinkles (that all continues to live in app/assets).
@@ -90,7 +90,7 @@ in which case you may not even need the asset pipeline. This is mostly relevant
9090

9191
## Features
9292

93-
* [Webpack 2](https://webpack.js.org/)
93+
* [Webpack 3.x.x](https://webpack.js.org/)
9494
* ES6 with [babel](https://babeljs.io/)
9595
* Automatic code splitting using multiple entry points
9696
* Stylesheets - SASS and CSS
@@ -199,21 +199,6 @@ any changes to the configuration files. An example component will
199199
also be added to your project in `app/javascript` so that you can
200200
experiment Vue right away.
201201

202-
#### Using Rails helpers in .vue files
203-
204-
Rails helpers cannot be used in `.vue` files by default. To enable them, change
205-
the extension to `.vue.erb` and additionally amend the `test` in
206-
`config/webpack/loaders/vue.js` to also include `.vue.erb` files:
207-
208-
```js
209-
# config/webpack/loaders/vue.js
210-
211-
module.exports = {
212-
test: /\.vue(\.erb)?$/,
213-
...
214-
}
215-
```
216-
217202
### Elm
218203

219204
To use Webpacker with [Elm](http://elm-lang.org), create a
@@ -268,10 +253,9 @@ precedence over the ones already set in the configuration file.
268253
### Webpack
269254

270255
Webpacker gives you a default set of configuration files for test, development and
271-
production environments. They all live together with the shared
272-
points in `config/webpack/*.js`.
273-
274-
![screen shot 2017-05-23 at 19 56 18](https://cloud.githubusercontent.com/assets/771039/26371229/0983add2-3ff2-11e7-9dc3-d9c2c1094032.png)
256+
production environments in `config/webpack/*.js`. You can configure each individual
257+
environment in their respective files or configure them all in the base
258+
`config/webpack/environment.js` file.
275259

276260
By default, you shouldn't have to make any changes to `config/webpack/*.js`
277261
files since it's all standard production-ready configuration. However,
@@ -280,28 +264,59 @@ if you do need to customize or add a new loader, this is where you would go.
280264

281265
### Loaders
282266

283-
Webpack enables the use of loaders to preprocess files. This allows you to
284-
bundle any static resource way beyond JavaScript. All base loaders
285-
that ship with webpacker are located inside `config/webpack/loaders`.
286-
287-
If you want to add a new loader, for example, to process `json` files via webpack:
267+
You can add additional loaders beyond the base set that webpacker provides by
268+
adding it to your environment. We'll use `json-loader` as an example:
288269

289270
```
290271
yarn add json-loader
291272
```
292273

293-
And create a `json.js` file inside `loaders` directory:
294-
295274
```js
296-
module.exports = {
275+
// config/webpack/environment.js
276+
const { environment } = require('@rails/webpacker')
277+
278+
environment.loaders.add('json', {
297279
test: /\.json$/,
298280
use: 'json-loader'
299-
}
281+
})
282+
283+
module.exports = environment
300284
```
301285

302286
Finally add `.json` to the list of extensions in `config/webpacker.yml`. Now if you `import()` any `.json` files inside your javascript
303287
they will be processed using `json-loader`. Voila!
304288

289+
You can also modify the loaders that webpacker pre-configures for you. We'll update
290+
the `babel` loader as an example:
291+
292+
```js
293+
// config/webpack/environment.js
294+
const { environment } = require('@rails/webpacker')
295+
296+
// Update an option directly
297+
const babelLoader = environment.loaders.get('babel')
298+
babelLoader.options.cacheDirectory = false
299+
300+
module.exports = environment
301+
```
302+
303+
### Plugins
304+
305+
The process for adding or modifying webpack plugins is the same as the process
306+
for loaders above:
307+
308+
```js
309+
// config/webpack/environment.js
310+
const { environment } = require('@rails/webpacker')
311+
312+
// Get a pre-configured plugin
313+
environment.plugins.get('ExtractText') // Is an ExtractTextPlugin instance
314+
315+
// Add an additional plugin of your choosing
316+
environment.plugins.add('Fancy', new MyFancyWebpackPlugin)
317+
318+
module.exports = environment
319+
```
305320

306321
### Paths
307322

@@ -409,7 +424,7 @@ Please note that the `webpack-dev-server` will use a self-signed certificate,
409424
so your web browser will display a warning/exception upon accessing the page. If you get
410425
`https://localhost:3035/sockjs-node/info?t=1503127986584 net::ERR_INSECURE_RESPONSE`
411426
in your console, simply open the link in your browser and accept the SSL exception.
412-
Now if you refresh your rails view everything should work as expected.
427+
Now if you refresh your rails view everything should work as expected.
413428

414429
### Hot module replacement
415430

@@ -664,9 +679,7 @@ Now, modify your Vue app to expect the properties.
664679

665680

666681
```js
667-
668682
document.addEventListener('DOMContentLoaded', () => {
669-
670683
// Get the properties BEFORE the app is instantiated
671684
const node = document.getElementById('hello-vue')
672685
const props = JSON.parse(node.getAttribute('data'))
@@ -685,41 +698,21 @@ You can follow same steps for Angular too.
685698

686699
The CommonsChunkPlugin is an opt-in feature that creates a separate file (known as a chunk), consisting of common modules shared between multiple entry points. By separating common modules from bundles, the resulting chunked file can be loaded once initially, and stored in the cache for later use. This results in page speed optimizations as the browser can quickly serve the shared code from the cache, rather than being forced to load a larger bundle whenever a new page is visited.
687700

688-
Create a `app-config.js` file inside `config/webpack` and in that file add:
701+
Add the plugins in `config/webpack/environment.js`:
689702

690703
```js
691-
module.exports = {
692-
plugins: [
693-
// Creates a common vendor.js with all shared modules
694-
new webpack.optimize.CommonsChunkPlugin({
695-
name: 'vendor',
696-
minChunks: (module) => {
697-
// this assumes your vendor imports exist in the node_modules directory
698-
return module.context && module.context.indexOf('node_modules') !== -1;
699-
}
700-
}),
701-
// Webpack code chunk - manifest.js
702-
new webpack.optimize.CommonsChunkPlugin({
703-
name: 'manifest',
704-
minChunks: Infinity
705-
})
706-
]
704+
environment.plugins.add('CommonsChunkVendor', new webpack.optimize.CommonsChunkPlugin({
705+
name: 'vendor',
706+
minChunks: (module) => {
707+
// this assumes your vendor imports exist in the node_modules directory
708+
return module.context && module.context.indexOf('node_modules') !== -1;
707709
}
708-
```
709-
710-
You can add this in `shared.js` too but we are doing this to ensure smoother upgrades.
711-
712-
```js
713-
// config/webpack/shared.js
714-
// .... rest of the config
715-
716-
const appConfig = require('./app-config.js')
717-
718-
plugins: appConfig.plugins.concat([
719-
720-
// ...existing plugins
710+
}))
721711

722-
])
712+
environment.plugins.add('CommonsChunkManifest', new webpack.optimize.CommonsChunkPlugin({
713+
name: 'manifest',
714+
minChunks: Infinity
715+
}))
723716
```
724717

725718
Now, add these files to your `layouts/application.html.erb`:
@@ -833,16 +826,7 @@ yarn remove prop-types
833826
}
834827
```
835828

836-
3. Add a new loader `config/webpack/loaders/typescript.js`:
837-
838-
``` js
839-
module.exports = {
840-
test: /.(ts|tsx)$/,
841-
loader: 'ts-loader'
842-
}
843-
```
844-
845-
4. Finally add `.tsx` to the list of extensions in `config/webpacker.yml`
829+
3. Finally add `.tsx` to the list of extensions in `config/webpacker.yml`
846830
and rename your generated `hello_react.js` using react installer
847831
to `hello_react.tsx` and make it valid typescript and now you can use
848832
typescript, JSX with React.
@@ -859,10 +843,10 @@ you would need to follow these steps to add HTML templates support:
859843
yarn add html-loader
860844
```
861845

862-
2. Add html-loader to `config/webpacker/loaders/html.js`
846+
2. Add html-loader to `config/webpack/environment.js`
863847

864848
```js
865-
module.exports = {
849+
environment.loaders.add('html', {
866850
test: /\.html$/,
867851
use: [{
868852
loader: 'html-loader',
@@ -874,7 +858,7 @@ module.exports = {
874858
customAttrAssign: [ /\)?\]?=/ ]
875859
}
876860
}]
877-
}
861+
})
878862
```
879863

880864
3. Add `.html` to `config/webpacker.yml`
@@ -921,48 +905,6 @@ export class AppComponent {
921905

922906
That's all. Voila!
923907

924-
925-
### CSS modules
926-
927-
To enable CSS modules, you would need to update `config/webpack/loaders/sass.js`
928-
file, particularly `css-loader`:
929-
930-
```js
931-
// Add css-modules
932-
933-
{
934-
loader: 'css-loader',
935-
options: {
936-
minimize: env.NODE_ENV === 'production',
937-
modules: true,
938-
localIdentName: '[path][name]__[local]--[hash:base64:5]'
939-
}
940-
}
941-
```
942-
943-
That's all. Now, you can use CSS modules within your JS app:
944-
945-
```js
946-
import React from 'react'
947-
import styles from './styles'
948-
949-
const Hello = props => (
950-
<div className={styles.wrapper}>
951-
<img src={clockIcon} alt="clock" className={styles.img} />
952-
<h5 className={styles.name}>
953-
{props.message} {props.name}!
954-
</h5>
955-
</div>
956-
)
957-
```
958-
959-
960-
### CSS-Next
961-
962-
[css-next](http://cssnext.io/) is supported out-of-box in Webpacker allowing the use of
963-
latest CSS features, today.
964-
965-
966908
### Ignoring swap files
967909

968910
If you are using vim or emacs and want to ignore certain files you can add `ignore-loader`:
@@ -971,16 +913,15 @@ If you are using vim or emacs and want to ignore certain files you can add `igno
971913
yarn add ignore-loader
972914
```
973915

974-
and create a new loader file inside `config/webpack/loaders`:
916+
and add `ignore-loader` to `config/webpack/environment.js`
975917

976918
```js
977-
// config/webpack/loaders/ignores.js
978919
// ignores vue~ swap files
979-
980-
module.exports = {
981-
test: /.vue~$/,
920+
const { environment } = require('@rails/webpacker')
921+
environment.loaders.add('ignore', {
922+
test: /.vue~$/,
982923
loader: 'ignore-loader'
983-
}
924+
})
984925
```
985926

986927
And now all files with `.vue~` will be ignored by the webpack compiler.
@@ -1068,7 +1009,7 @@ yarn add dotenv
10681009
```
10691010

10701011
```javascript
1071-
// config/webpack/shared.js
1012+
// config/webpack/environment.js
10721013
10731014
...
10741015
const dotenv = require('dotenv');
@@ -1097,44 +1038,6 @@ If you'd like to pass custom variables to the compiler, use `Webpack::Compiler.e
10971038
Webpacker::Compiler.env['FRONTEND_API_KEY'] = 'your_secret_key'
10981039
```
10991040

1100-
## Extending
1101-
1102-
We suggest you don't directly overwrite the provided configuration files
1103-
and extend instead for smoother upgrades. Here is one way to do it:
1104-
1105-
Create a `app-config.js` file inside `config/webpack`, and in that add:
1106-
1107-
```js
1108-
module.exports = {
1109-
production: {
1110-
plugins: [
1111-
// ... Add plugins
1112-
]
1113-
},
1114-
1115-
development: {
1116-
output: {
1117-
// ... Custom output path
1118-
}
1119-
}
1120-
}
1121-
```
1122-
1123-
```js
1124-
// config/webpack/production.js
1125-
1126-
const { plugins } = require('./app-config.js')
1127-
1128-
plugins: appConfig.plugins.concat([
1129-
1130-
// ...existing plugins
1131-
1132-
])
1133-
```
1134-
1135-
But this could be done million other ways.
1136-
1137-
11381041
## Deployment
11391042

11401043
Webpacker hooks up a new `webpacker:compile` task to `assets:precompile`, which gets run whenever you run `assets:precompile`. If you are not using sprockets you
@@ -1226,13 +1129,6 @@ by adding new paths to `watched_paths` array, much like rails `autoload_paths`:
12261129
Webpacker::Compiler.watched_paths << 'bower_components'
12271130
```
12281131

1229-
Compiler stores a timestamp under `tmp/webpacker/` directory to keep track of
1230-
changes and you can configure that by overriding compiler `cache_dir`:
1231-
1232-
```rb
1233-
Webpacker::Compiler.cache_dir = "tmp/foo"
1234-
```
1235-
12361132
## Troubleshooting
12371133

12381134
##### ENOENT: no such file or directory - node-sass

lib/install/angular.rb

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,5 @@
11
require "webpacker/configuration"
22

3-
puts "Copying angular loader to config/webpack/loaders"
4-
copy_file "#{__dir__}/config/loaders/installers/angular.js", "config/webpack/loaders/angular.js"
5-
63
puts "Copying angular example entry file to #{Webpacker.config.source_entry_path}"
74
copy_file "#{__dir__}/examples/angular/hello_angular.js", "#{Webpacker.config.source_entry_path}/hello_angular.js"
85

lib/install/config/loaders/core/assets.js

Lines changed: 0 additions & 15 deletions
This file was deleted.

0 commit comments

Comments
 (0)