webpacker-react 0.1.0 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.github/PULL_REQUEST_TEMPLATE +9 -0
- data/CHANGELOG.md +21 -0
- data/CODE_OF_CONDUCT.md +74 -0
- data/README.md +45 -15
- data/_config.yml +1 -0
- data/circle.yml +6 -2
- data/javascript/webpacker_react-npm-module/.eslintrc.js +15 -0
- data/javascript/webpacker_react-npm-module/dist/package.json +1 -1
- data/javascript/webpacker_react-npm-module/package.json +11 -2
- data/javascript/webpacker_react-npm-module/src/configure-hot-module-replacement.js +11 -11
- data/javascript/webpacker_react-npm-module/src/hmr.js +3 -3
- data/javascript/webpacker_react-npm-module/src/index.js +46 -42
- data/javascript/webpacker_react-npm-module/src/ujs.js +85 -0
- data/javascript/webpacker_react-npm-module/yarn.lock +764 -25
- data/lib/webpacker/react/version.rb +1 -1
- metadata +8 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: ab20541e11a8ca3cfda69b8359711dc6ec01b878
|
4
|
+
data.tar.gz: 44795485fe7bdec875cdc9975bfb5c79d036dcc0
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 89a2087cf23242199f588d80139f809fb35b87a5b3abc530bd7ad2ff0aea3c08c399a3bd7bd875b5cd5b2b7d7d1e5a7a19028bee27d7066ce523e007186fd409
|
7
|
+
data.tar.gz: b20d46ad6d1ac3dfb130aa6c691be91738b879ec4d457fa84f25f8a40f9bee175da743d5180f1af50cfd8f3abf5a8d6801ca6931a394f26a40543be033135a10
|
@@ -0,0 +1,9 @@
|
|
1
|
+
Fixes # .
|
2
|
+
|
3
|
+
Changes:
|
4
|
+
|
5
|
+
Please ensure that:
|
6
|
+
- [ ] Changelog is updated if not a minor patch
|
7
|
+
- [ ] Ruby linting is ok: `rubocop` is all green
|
8
|
+
- [ ] Javascript linting is ok: `cd javascript/webpacker_react-npm-module/ && yarn lint` is all green
|
9
|
+
- [ ] [Tests](https://github.com/renchap/webpacker-react#testing) are all green
|
data/CHANGELOG.md
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
# Change Log
|
2
|
+
All notable changes to this project will be documented in this file.
|
3
|
+
|
4
|
+
The format is based on [Keep a Changelog](http://keepachangelog.com/)
|
5
|
+
and this project adheres to [Semantic Versioning](http://semver.org/).
|
6
|
+
|
7
|
+
## [Unreleased]
|
8
|
+
## 0.2.0 - 2017-03-20
|
9
|
+
### Added
|
10
|
+
- support for Turbolinks 5, Turbolinks 2.4 and PJAX. Components will be mounted and unmounted when Turbolinks-specific events occur. Also, the integration works with Turbolinks 5 cache.
|
11
|
+
- New `WebpackerReact.setup({Component1, Component2, ...})` initialization API. The old API couldn't properly detect the components' names, thus user is required to provide the names in the configuration object's keys.
|
12
|
+
### Removed
|
13
|
+
- `WebpackerReact.register(Component)` has been dropped in favor of `WebpackerReact.setup({Component})`
|
14
|
+
## 0.1.0 - 2017-02-23
|
15
|
+
### Added
|
16
|
+
- First released version
|
17
|
+
- render React components from views using the `react_component` helper
|
18
|
+
- render React components from controllers using `render react_component: 'name'` (#1 by @daninfpj)
|
19
|
+
- basic Hot Module Remplacement (#7 by @mfazekas)
|
20
|
+
|
21
|
+
[Unreleased]: https://github.com/renchap/webpacker-react/compare/v0.1.0...HEAD
|
data/CODE_OF_CONDUCT.md
ADDED
@@ -0,0 +1,74 @@
|
|
1
|
+
# Contributor Covenant Code of Conduct
|
2
|
+
|
3
|
+
## Our Pledge
|
4
|
+
|
5
|
+
In the interest of fostering an open and welcoming environment, we as
|
6
|
+
contributors and maintainers pledge to making participation in our project and
|
7
|
+
our community a harassment-free experience for everyone, regardless of age, body
|
8
|
+
size, disability, ethnicity, gender identity and expression, level of experience,
|
9
|
+
nationality, personal appearance, race, religion, or sexual identity and
|
10
|
+
orientation.
|
11
|
+
|
12
|
+
## Our Standards
|
13
|
+
|
14
|
+
Examples of behavior that contributes to creating a positive environment
|
15
|
+
include:
|
16
|
+
|
17
|
+
* Using welcoming and inclusive language
|
18
|
+
* Being respectful of differing viewpoints and experiences
|
19
|
+
* Gracefully accepting constructive criticism
|
20
|
+
* Focusing on what is best for the community
|
21
|
+
* Showing empathy towards other community members
|
22
|
+
|
23
|
+
Examples of unacceptable behavior by participants include:
|
24
|
+
|
25
|
+
* The use of sexualized language or imagery and unwelcome sexual attention or
|
26
|
+
advances
|
27
|
+
* Trolling, insulting/derogatory comments, and personal or political attacks
|
28
|
+
* Public or private harassment
|
29
|
+
* Publishing others' private information, such as a physical or electronic
|
30
|
+
address, without explicit permission
|
31
|
+
* Other conduct which could reasonably be considered inappropriate in a
|
32
|
+
professional setting
|
33
|
+
|
34
|
+
## Our Responsibilities
|
35
|
+
|
36
|
+
Project maintainers are responsible for clarifying the standards of acceptable
|
37
|
+
behavior and are expected to take appropriate and fair corrective action in
|
38
|
+
response to any instances of unacceptable behavior.
|
39
|
+
|
40
|
+
Project maintainers have the right and responsibility to remove, edit, or
|
41
|
+
reject comments, commits, code, wiki edits, issues, and other contributions
|
42
|
+
that are not aligned to this Code of Conduct, or to ban temporarily or
|
43
|
+
permanently any contributor for other behaviors that they deem inappropriate,
|
44
|
+
threatening, offensive, or harmful.
|
45
|
+
|
46
|
+
## Scope
|
47
|
+
|
48
|
+
This Code of Conduct applies both within project spaces and in public spaces
|
49
|
+
when an individual is representing the project or its community. Examples of
|
50
|
+
representing a project or community include using an official project e-mail
|
51
|
+
address, posting via an official social media account, or acting as an appointed
|
52
|
+
representative at an online or offline event. Representation of a project may be
|
53
|
+
further defined and clarified by project maintainers.
|
54
|
+
|
55
|
+
## Enforcement
|
56
|
+
|
57
|
+
Instances of abusive, harassing, or otherwise unacceptable behavior may be
|
58
|
+
reported by contacting the project maintainer at renchap@gmail.com. All
|
59
|
+
complaints will be reviewed and investigated and will result in a response that
|
60
|
+
is deemed necessary and appropriate to the circumstances. The project team is
|
61
|
+
obligated to maintain confidentiality with regard to the reporter of an incident.
|
62
|
+
Further details of specific enforcement policies may be posted separately.
|
63
|
+
|
64
|
+
Project maintainers who do not follow or enforce the Code of Conduct in good
|
65
|
+
faith may face temporary or permanent repercussions as determined by other
|
66
|
+
members of the project's leadership.
|
67
|
+
|
68
|
+
## Attribution
|
69
|
+
|
70
|
+
This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4,
|
71
|
+
available at [http://contributor-covenant.org/version/1/4][version]
|
72
|
+
|
73
|
+
[homepage]: http://contributor-covenant.org
|
74
|
+
[version]: http://contributor-covenant.org/version/1/4/
|
data/README.md
CHANGED
@@ -22,20 +22,16 @@ Your Rails application needs to use Webpacker and have the React integration don
|
|
22
22
|
First, you need to add the webpacker-react gem to your Rails app Gemfile:
|
23
23
|
|
24
24
|
```ruby
|
25
|
-
gem 'webpacker-react', "~>0.1.0"
|
25
|
+
gem 'webpacker-react', "~> 0.1.0"
|
26
26
|
```
|
27
27
|
|
28
|
-
Once done, run `
|
28
|
+
Once done, run `bundle` to install the gem.
|
29
29
|
|
30
|
-
Then you need to update your `
|
31
|
-
|
32
|
-
|
33
|
-
"..."
|
34
|
-
"webpacker-react": "~>0.1.0"
|
35
|
-
},
|
36
|
-
```
|
30
|
+
Then you need to update your `package.json` file to include the `webpacker-react` NPM module:
|
31
|
+
|
32
|
+
`./bin/yarn add webpacker-react`
|
37
33
|
|
38
|
-
|
34
|
+
You are now all set!
|
39
35
|
|
40
36
|
### Note about versions
|
41
37
|
|
@@ -50,9 +46,33 @@ In your pack file (`app/javascript/packs/*.js`), import your components as well
|
|
50
46
|
import Hello from 'components/hello'
|
51
47
|
import WebpackerReact from 'webpacker-react'
|
52
48
|
|
53
|
-
WebpackerReact.
|
49
|
+
WebpackerReact.setup({Hello}) // ES6 shorthand for {Hello: Hello}
|
54
50
|
```
|
55
51
|
|
52
|
+
### With Turbolinks
|
53
|
+
|
54
|
+
You have to make sure Turbolinks is loaded before calling `WebpackerReact.initialize()`.
|
55
|
+
|
56
|
+
For example:
|
57
|
+
|
58
|
+
```javascript
|
59
|
+
import Hello from 'components/hello'
|
60
|
+
import WebpackerReact from 'webpacker-react'
|
61
|
+
import Turbolinks from 'turbolinks'
|
62
|
+
|
63
|
+
Turbolinks.start()
|
64
|
+
|
65
|
+
WebpackerReact.setup({Hello})
|
66
|
+
```
|
67
|
+
|
68
|
+
You may also load turbolinks in regular asset pipeline `application.js`:
|
69
|
+
|
70
|
+
```javascript
|
71
|
+
//= require "turbolinks"
|
72
|
+
```
|
73
|
+
|
74
|
+
In that case, make sure your packs are loaded *after* `application.js`
|
75
|
+
|
56
76
|
Now you can render React components from your views or your controllers.
|
57
77
|
|
58
78
|
### Rendering from a view
|
@@ -101,7 +121,7 @@ significantly different than the standard Webpacker config:
|
|
101
121
|
var configureHotModuleReplacement = require('webpacker-react/configure-hot-module-replacement')
|
102
122
|
|
103
123
|
var sharedConfig = require('./shared.js')
|
104
|
-
sharedConfig = configureHotModuleReplacement(sharedConfig)
|
124
|
+
sharedConfig.config = configureHotModuleReplacement(sharedConfig.config)
|
105
125
|
|
106
126
|
module.exports = merge(sharedConfig, ...)
|
107
127
|
```
|
@@ -160,7 +180,7 @@ and start `webpack-dev-server` in hot replacement mode:
|
|
160
180
|
import SomeRootReactComponent from 'components/some-root-react-component'
|
161
181
|
import WebpackerReact from 'webpacker-react/hmr'
|
162
182
|
|
163
|
-
WebpackerReact.
|
183
|
+
WebpackerReact.setup({SomeRootReactComponent})
|
164
184
|
if (module.hot)
|
165
185
|
module.hot.accept('components/some-root-react-component', () =>
|
166
186
|
WebpackerReact.renderOnHMR(SomeRootReactComponent) )
|
@@ -179,12 +199,15 @@ gem 'webpacker-react', path: '~/code/webpacker-react/'
|
|
179
199
|
Finally, you need to tell Yarn to use your local copy of the NPM module in this application, using [`yarn link`](https://yarnpkg.com/en/docs/cli/link):
|
180
200
|
|
181
201
|
```
|
182
|
-
$ cd ~/code/webpacker-react/javascript/webpacker_react-npm-module/
|
183
|
-
$ yarn
|
202
|
+
$ cd ~/code/webpacker-react/javascript/webpacker_react-npm-module/
|
203
|
+
$ yarn
|
204
|
+
$ cd dist/
|
205
|
+
$ yarn # compiles the code from src/ to dist/
|
184
206
|
$ yarn link
|
185
207
|
success Registered "webpacker-react".
|
186
208
|
info You can now run `yarn link "webpacker-react"` in the projects where you want to use this module and it will be used instead.
|
187
209
|
$ cd ~/code/webpacker-react-example/
|
210
|
+
$ yarn link webpacker-react
|
188
211
|
success Registered "webpacker-react".
|
189
212
|
```
|
190
213
|
|
@@ -212,6 +235,13 @@ Finally, run the test suite:
|
|
212
235
|
$ rake test
|
213
236
|
```
|
214
237
|
|
238
|
+
If you change the javascript code, please ensure there are no style errors:
|
239
|
+
|
240
|
+
```sh
|
241
|
+
$ cd javascript/webpacker_react-npm-module/
|
242
|
+
$ yarn lint
|
243
|
+
```
|
244
|
+
|
215
245
|
## Contributing
|
216
246
|
|
217
247
|
Bug reports and pull requests are welcome on GitHub at https://github.com/renchap/webpacker-react.
|
data/_config.yml
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
theme: jekyll-theme-cayman
|
data/circle.yml
CHANGED
@@ -9,9 +9,13 @@ checkout:
|
|
9
9
|
pwd: javascript/webpacker_react-npm-module/dist
|
10
10
|
- yarn link:
|
11
11
|
pwd: javascript/webpacker_react-npm-module/dist
|
12
|
-
|
13
|
-
|
12
|
+
compile:
|
13
|
+
override:
|
14
14
|
- test/example_app/bin/yarn
|
15
15
|
- yarn link webpacker-react:
|
16
16
|
pwd: test/example_app/vendor
|
17
17
|
- test/example_app/bin/webpack
|
18
|
+
test:
|
19
|
+
pre:
|
20
|
+
- yarn lint:
|
21
|
+
pwd: javascript/webpacker_react-npm-module
|
@@ -0,0 +1,15 @@
|
|
1
|
+
module.exports = {
|
2
|
+
'extends': 'airbnb',
|
3
|
+
'rules': {
|
4
|
+
'comma-dangle': ['error', 'never'],
|
5
|
+
'import/no-unresolved': 'off',
|
6
|
+
'import/no-extraneous-dependencies': 'off',
|
7
|
+
'import/extensions': 'off',
|
8
|
+
'no-console': 'off',
|
9
|
+
semi: ['error', 'never'],
|
10
|
+
},
|
11
|
+
'env': {
|
12
|
+
'browser': true,
|
13
|
+
'node': true,
|
14
|
+
},
|
15
|
+
}
|
@@ -2,10 +2,19 @@
|
|
2
2
|
"name": "webpacker-react-build",
|
3
3
|
"private": true,
|
4
4
|
"scripts": {
|
5
|
-
"build": "babel src --presets=babel-preset-es2015 --out-dir dist"
|
5
|
+
"build": "babel src --presets=babel-preset-es2015 --out-dir dist",
|
6
|
+
"lint": "eslint src/"
|
6
7
|
},
|
7
8
|
"devDependencies": {
|
8
9
|
"babel-cli": "^6.18.0",
|
9
|
-
"babel-preset-es2015": "^6.
|
10
|
+
"babel-preset-es2015": "^6.22.0",
|
11
|
+
"eslint": "^3.16.1",
|
12
|
+
"eslint-config-airbnb": "^14.1.0",
|
13
|
+
"eslint-plugin-import": "^2.2.0",
|
14
|
+
"eslint-plugin-jsx-a11y": "^4.0.0",
|
15
|
+
"eslint-plugin-react": "^6.10.0"
|
16
|
+
},
|
17
|
+
"dependencies": {
|
18
|
+
"lodash": "^4.0.0"
|
10
19
|
}
|
11
20
|
}
|
@@ -1,13 +1,14 @@
|
|
1
1
|
import webpack from 'webpack'
|
2
2
|
import merge from 'webpack-merge'
|
3
3
|
|
4
|
-
function configureHotModuleReplacement(
|
5
|
-
|
6
|
-
config = merge(
|
7
|
-
|
4
|
+
function configureHotModuleReplacement(originalConfig) {
|
5
|
+
const webpackDevServerAddr = process.env.WEBPACK_DEV_SERVER_ADDR || 'http://localhost:8080/'
|
6
|
+
const config = merge(
|
7
|
+
originalConfig,
|
8
8
|
{
|
9
9
|
output: {
|
10
|
-
|
10
|
+
// needed for HMR to know where to load the hot update chunks
|
11
|
+
publicPath: webpackDevServerAddr
|
11
12
|
},
|
12
13
|
plugins: [
|
13
14
|
new webpack.NamedModulesPlugin()
|
@@ -15,20 +16,19 @@ function configureHotModuleReplacement(config) {
|
|
15
16
|
}
|
16
17
|
)
|
17
18
|
|
18
|
-
config.module.rules = config.module.rules.map(
|
19
|
+
config.module.rules = config.module.rules.map((rule) => {
|
19
20
|
if (rule.loader === 'babel-loader') {
|
20
|
-
return merge(rule, {options: {plugins: ['react-hot-loader/babel']}})
|
21
|
-
} else {
|
22
|
-
return rule
|
21
|
+
return merge(rule, { options: { plugins: ['react-hot-loader/babel'] } })
|
23
22
|
}
|
23
|
+
return rule
|
24
24
|
})
|
25
25
|
|
26
|
-
|
26
|
+
Object.keys(config.entry).forEach((key) => {
|
27
27
|
if (!(config.entry[key] instanceof Array)) {
|
28
28
|
config.entry[key] = [config.entry[key]]
|
29
29
|
}
|
30
30
|
config.entry[key].unshift('react-hot-loader/patch')
|
31
|
-
}
|
31
|
+
})
|
32
32
|
return config
|
33
33
|
}
|
34
34
|
|
@@ -2,8 +2,8 @@ import { AppContainer } from 'react-hot-loader'
|
|
2
2
|
import WebpackerReact from 'webpacker-react'
|
3
3
|
import React from 'react'
|
4
4
|
|
5
|
-
WebpackerReact.registerWrapForHMR(
|
6
|
-
|
7
|
-
|
5
|
+
WebpackerReact.registerWrapForHMR(reactElement =>
|
6
|
+
React.createElement(AppContainer, {}, reactElement)
|
7
|
+
)
|
8
8
|
|
9
9
|
export default WebpackerReact
|
@@ -1,17 +1,18 @@
|
|
1
1
|
import React from 'react'
|
2
2
|
import ReactDOM from 'react-dom'
|
3
|
+
import { intersection, keys, assign, omit } from 'lodash'
|
4
|
+
import ujs from './ujs'
|
3
5
|
|
4
6
|
const CLASS_ATTRIBUTE_NAME = 'data-react-class'
|
5
7
|
const PROPS_ATTRIBUTE_NAME = 'data-react-props'
|
6
8
|
|
7
|
-
|
8
|
-
|
9
|
-
registeredComponents : {},
|
9
|
+
const WebpackerReact = {
|
10
|
+
registeredComponents: {},
|
10
11
|
wrapForHMR: null,
|
11
12
|
|
12
|
-
render
|
13
|
-
|
14
|
-
|
13
|
+
render(node, component) {
|
14
|
+
const propsJson = node.getAttribute(PROPS_ATTRIBUTE_NAME)
|
15
|
+
const props = propsJson && JSON.parse(propsJson)
|
15
16
|
|
16
17
|
let reactElement = React.createElement(component, props)
|
17
18
|
if (this.wrapForHMR) {
|
@@ -20,17 +21,18 @@ var WebpackerReact = {
|
|
20
21
|
ReactDOM.render(reactElement, node)
|
21
22
|
},
|
22
23
|
|
23
|
-
renderOnHMR
|
24
|
-
|
24
|
+
renderOnHMR(component) {
|
25
|
+
const name = component.name
|
26
|
+
|
25
27
|
this.registeredComponents[name] = component
|
26
28
|
|
27
29
|
if (!this.wrapForHMR) {
|
28
|
-
console.warn('
|
30
|
+
console.warn('webpacker-react: renderOnHMR called but not elements not wrapped for HMR')
|
29
31
|
}
|
30
32
|
|
31
|
-
|
32
|
-
for (
|
33
|
-
|
33
|
+
const toMount = document.querySelectorAll(`[${CLASS_ATTRIBUTE_NAME}=${name}]`)
|
34
|
+
for (let i = 0; i < toMount.length; i += 1) {
|
35
|
+
const node = toMount[i]
|
34
36
|
|
35
37
|
this.render(node, component)
|
36
38
|
}
|
@@ -40,47 +42,49 @@ var WebpackerReact = {
|
|
40
42
|
this.wrapForHMR = wrapForHMR
|
41
43
|
},
|
42
44
|
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
console.warn('webpacker-react: Cant register component, another one with this name is already registered: ' + name)
|
48
|
-
return false
|
45
|
+
registerComponents(components) {
|
46
|
+
const collisions = intersection(keys(this.registeredComponents), keys(components))
|
47
|
+
if (collisions.length > 0) {
|
48
|
+
console.error(`webpacker-react: can not register components. Following components are already registered: ${collisions}`)
|
49
49
|
}
|
50
50
|
|
51
|
-
this.registeredComponents
|
51
|
+
assign(this.registeredComponents, omit(components, collisions))
|
52
52
|
return true
|
53
53
|
},
|
54
54
|
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
console.warn("webpacker-react: events have already been registered")
|
60
|
-
return false
|
55
|
+
unmountComponents() {
|
56
|
+
const mounted = document.querySelectorAll(`[${CLASS_ATTRIBUTE_NAME}]`)
|
57
|
+
for (let i = 0; i < mounted.length; i += 1) {
|
58
|
+
ReactDOM.unmountComponentAtNode(mounted[i])
|
61
59
|
}
|
60
|
+
},
|
62
61
|
|
63
|
-
|
64
|
-
|
62
|
+
mountComponents() {
|
63
|
+
const registeredComponents = this.registeredComponents
|
64
|
+
const toMount = document.querySelectorAll(`[${CLASS_ATTRIBUTE_NAME}]`)
|
65
65
|
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
66
|
+
for (let i = 0; i < toMount.length; i += 1) {
|
67
|
+
const node = toMount[i]
|
68
|
+
const className = node.getAttribute(CLASS_ATTRIBUTE_NAME)
|
69
|
+
const component = registeredComponents[className]
|
70
70
|
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
}
|
71
|
+
if (component) {
|
72
|
+
if (node.innerHTML.length === 0) this.render(node, component)
|
73
|
+
} else {
|
74
|
+
console.error(`webpacker-react: cant render a component that has not been registered: ${className}`)
|
76
75
|
}
|
77
|
-
}
|
76
|
+
}
|
77
|
+
},
|
78
78
|
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
79
|
+
setup(components = {}) {
|
80
|
+
if (typeof window.WebpackerReact === 'undefined') {
|
81
|
+
window.WebpackerReact = this
|
82
|
+
ujs.setup(this.mountComponents.bind(this), this.unmountComponents.bind(this))
|
83
|
+
}
|
83
84
|
|
84
|
-
WebpackerReact.
|
85
|
+
window.WebpackerReact.registerComponents(components)
|
86
|
+
window.WebpackerReact.mountComponents()
|
87
|
+
}
|
88
|
+
}
|
85
89
|
|
86
90
|
export default WebpackerReact
|