Skip to content

Commit

Permalink
feat: feature freeze on wpackio/scripts
Browse files Browse the repository at this point in the history
No more featured needed for v1. Let's focus on finishing up.
  • Loading branch information
swashata committed Oct 11, 2018
1 parent 5c45bfb commit fe61b48
Show file tree
Hide file tree
Showing 17 changed files with 284 additions and 22 deletions.
3 changes: 3 additions & 0 deletions examples/plugin/.vscode/settings.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
"eslint.autoFixOnSave": true
}
5 changes: 5 additions & 0 deletions examples/plugin/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -14,5 +14,10 @@
"scripts": {
"exstart": "wpackio-scripts start",
"exbuild": "wpackio-scripts build"
},
"dependencies": {
"react": "^16.5.2",
"react-dom": "^16.5.2",
"react-hot-loader": "^4.3.11"
}
}
3 changes: 2 additions & 1 deletion examples/plugin/src/app/index.css
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,8 @@ body {
background-color: black !important;
}

/* CSS HMR */
.site-title a {
color: slategray !important;
color: azure !important;
background-color: aqua !important;
}
4 changes: 3 additions & 1 deletion examples/plugin/src/app/mobile.js
Original file line number Diff line number Diff line change
@@ -1 +1,3 @@
console.log('Hello Mobile!!');
// Auto page load when HMR is not defined

console.log('Hello Mobile!');
2 changes: 1 addition & 1 deletion examples/plugin/src/app/modules/dynamic.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
export default function iAmGroot() {
console.log('I am dynamic groot! With Hot reloading!😱💩');
console.log('I am dynamic groot! With Hot reloading!😱🐶');
}
3 changes: 2 additions & 1 deletion examples/plugin/src/app/modules/logger.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
export default function logger() {
console.log('Load me 🤟🎉💥😜');
// Automatic Hot Module Replacement
console.log('Load me 🤟🎉💥😜😺');
}
15 changes: 15 additions & 0 deletions examples/plugin/src/reactapp/App.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import React from 'react';
import { hot } from 'react-hot-loader';
import Box from './components/Box';
import Todo from './components/Todo';

const App = () => (
<Box heading="Hello From React">
<p>I can be hot reloaded!</p>
<p>Heres something of an app.</p>
<h4>Todo App.!</h4>
<Todo />
</Box>
);

export default hot(module)(App);
10 changes: 10 additions & 0 deletions examples/plugin/src/reactapp/components/Box.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import React from 'react';

const Box = ({ heading, children }) => (
<div className="box">
<h2>{heading}</h2>
<div className="box__content">{children}</div>
</div>
);

export default Box;
11 changes: 11 additions & 0 deletions examples/plugin/src/reactapp/components/List.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import React from 'react';

const List = ({ items }) => (
<ul>
{items.map((item, index) => (
<li key={index}>{item}</li>
))}
</ul>
);

export default List;
37 changes: 37 additions & 0 deletions examples/plugin/src/reactapp/components/Todo.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
import React, { Component } from 'react';
import List from './List';

export default class Todo extends Component {
constructor(props) {
super(props);
this.state = {
term: '',
items: [],
};
}

onChange = event => {
this.setState({ term: event.target.value });
};

onSubmit = event => {
event.preventDefault();
this.setState(state => ({
term: '',
items: [...state.items, state.term],
}));
};

render() {
const { term, items } = this.state;
return (
<div>
<form className="App" onSubmit={this.onSubmit}>
<input value={term} onChange={this.onChange} />
<button type="submit">Add+</button>
</form>
<List items={items} />
</div>
);
}
}
8 changes: 8 additions & 0 deletions examples/plugin/src/reactapp/index.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
import React from 'react';
import { render } from 'react-dom';
import App from './App';

document.addEventListener('DOMContentLoaded', () => {
const entry = document.querySelector('#wpackio-reactapp');
render(<App />, entry);
});
43 changes: 35 additions & 8 deletions examples/plugin/wpackio-plugin.php
Original file line number Diff line number Diff line change
Expand Up @@ -19,14 +19,41 @@
* License URI: http://www.gnu.org/licenses/gpl-2.0.txt
*/

// Create an admin page
add_action( 'wp_enqueue_scripts', 'wpackio_plugin_enqueue' );
// Get our dependency
require_once dirname( __FILE__ ) . '/inc/Enqueue.php';
$enqueue = new \WPackio\Enqueue( 'wpackplugin', 'dist', '1.0.0', 'plugin', __FILE__ );

function wpackio_plugin_enqueue() {
global $enqueue;
$enqueue->enqueue( 'app', 'main', [] );
$enqueue->enqueue( 'app', 'mobile', [] );
$enqueue->enqueue( 'foo', 'main', [] );
// Do stuff through this plugin
class WPackioPluginInit {
/**
* @var \WPackio\Enqueue
*/
public $enqueue;

public function __construct() {
// It is important that we init the Enqueue class right at the plugin/theme load time
$this->enqueue = new \WPackio\Enqueue( 'wpackplugin', 'dist', '1.0.0', 'plugin', __FILE__ );
// Enqueue a few of our entry points
add_action( 'wp_enqueue_scripts', [ $this, 'plugin_enqueue' ] );
// And heres a react app with shortcode
add_shortcode( 'wpackio-reactapp', [ $this, 'reactapp' ] );
}


function plugin_enqueue() {
$this->enqueue->enqueue( 'app', 'main', [] );
$this->enqueue->enqueue( 'app', 'mobile', [] );
$this->enqueue->enqueue( 'foo', 'main', [] );
}

function reactapp( $atts, $content = null ) {
// Enqueue our react app scripts
$this->enqueue->enqueue( 'reactapp', 'main', [] );

// Print the entry point
return '<div id="wpackio-reactapp"></div>';
}
}


// Init
new WPackioPluginInit();
12 changes: 12 additions & 0 deletions examples/plugin/wpackio.project.js
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,13 @@ module.exports = {
// Extra webpack config to be passed directly
webpackConfig: undefined,
},
// Another app just for showing react
{
name: 'reactapp',
entry: {
main: ['./src/reactapp/index.jsx'],
},
},
],
// Output path relative to the context directory
// We need relative path here, else, we can not map to publicPath
Expand All @@ -59,4 +66,9 @@ module.exports = {
optimizeSplitChunks: true,
// Usually PHP and other files to watch and reload when changed
watch: 'inc/**/*.php',
// Hook into babeloverride so that we can add react-hot-loader plugin
jsBabelOverride: defaults => ({
...defaults,
plugins: ['react-hot-loader/babel'],
}),
};
44 changes: 43 additions & 1 deletion packages/scripts/__tests__/config/WebpackConfigHelper.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import webpack from 'webpack';
import {
ProjectConfig,
projectConfigDefault,
webpackOptionsOverrideFunction,
} from '../../src/config/project.config.default';
import {
ServerConfig,
Expand Down Expand Up @@ -314,7 +315,7 @@ describe('CreateWebPackConfig', () => {
}
});

test('overrides all babel-loader options from config', () => {
test('overrides all babel-loader options from config object', () => {
const override: webpack.RuleSetLoader['options'] = {
presets: 'foo',
plugins: ['bar', 'baz'],
Expand Down Expand Up @@ -347,6 +348,47 @@ describe('CreateWebPackConfig', () => {
throw new Error('Module is not an array');
}
});

test('overrides all babel-loader options from config function', () => {
const override: webpackOptionsOverrideFunction = defaults => {
if (typeof defaults === 'string') {
return defaults;
}
return {
...defaults,
plugins: ['react-hot-loader/babel'],
};
};
const cwc = new WebpackConfigHelper(
projectConfig.files[0],
{
...getConfigFromProjectAndServer(
projectConfig,
serverConfig
),
jsBabelOverride: override,
tsBabelOverride: override,
},
'/foo/bar',
true
);
const modules = cwc.getModule();
if (Array.isArray(modules.rules)) {
const jsTsRules = findWpackIoBabelOnTJs(modules);
expect(jsTsRules).toHaveLength(2);
jsTsRules.forEach(rule => {
if (rule && rule.use && rule.use[0].options) {
expect(rule.use[0].options).toMatchObject({
plugins: ['react-hot-loader/babel'],
});
} else {
throw new Error('JavaScript rule is undefined');
}
});
} else {
throw new Error('Module is not an array');
}
});
});

test('uses style loader when in dev mode', () => {
Expand Down
13 changes: 11 additions & 2 deletions packages/scripts/src/config/WebpackConfigHelper.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@ import {
BannerConfig,
FileConfig,
ProjectConfig,
webpackLoaderOptionsOverride,
webpackOptionsOverrideFunction,
} from './project.config.default';
import { ServerConfig } from './server.config.default';

Expand Down Expand Up @@ -455,11 +457,18 @@ ${bannerConfig.copyrightText}${bannerConfig.credit ? creditNote : ''}`,
*/
private getOverrideWebpackRuleOptions(
defaults: webpack.RuleSetLoader['options'],
override: webpack.RuleSetLoader['options'] | undefined
override: webpackLoaderOptionsOverride
): webpack.RuleSetLoader['options'] {
// If override is not undefined or null, then return it
if (override != null) {
return override;
// If it is a function
if (typeof override === 'function') {
return (override as webpackOptionsOverrideFunction)(
defaults || {}
) as webpack.RuleSetLoader['options'];
} else {
return override;
}
}
// Otherwise just return default
return defaults;
Expand Down
19 changes: 15 additions & 4 deletions packages/scripts/src/config/project.config.default.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,19 @@ export interface FileConfig {
webpackConfig?: webpack.Configuration;
}

export type webpackOptionsOverrideFunction = (
// tslint:disable-next-line:no-any
defaults: string | { [x: string]: any }
) => // tslint:disable-next-line:no-any
string | { [x: string]: any };

export type webpackLoaderOptionsOverride =
| webpackOptionsOverrideFunction
// tslint:disable-next-line:no-any
| { [x: string]: any }
| string
| undefined;

/**
* Main Project Config shape under `wpackio.project.js` file.
*/
Expand Down Expand Up @@ -61,11 +74,9 @@ export interface ProjectConfig {
// If provided it is spread over whatever wpackio/scripts generates
tsBabelPresetOptions?: PresetOptions;
// Completely overrides `babel-loader` options for javascript files
// tslint:disable-next-line:no-any
jsBabelOverride?: string | { [x: string]: any };
jsBabelOverride?: webpackLoaderOptionsOverride;
// Completely overrides `babel-loader` options for typescript files
// tslint:disable-next-line:no-any
tsBabelOverride?: string | { [x: string]: any };
tsBabelOverride?: webpackLoaderOptionsOverride;
externals?: webpack.Configuration['externals'];
alias?: webpack.Resolve['alias'];
errorOverlay?: boolean;
Expand Down
Loading

0 comments on commit fe61b48

Please sign in to comment.