Skip to content

Commit

Permalink
update rxjs,webpack
Browse files Browse the repository at this point in the history
  • Loading branch information
tsker committed Apr 29, 2018
1 parent 539222d commit 0b47c90
Show file tree
Hide file tree
Showing 11 changed files with 118 additions and 101 deletions.
5 changes: 3 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -50,8 +50,9 @@
"react-router-dom": "^4.2.2",
"redux": "^4.0.0",
"redux-observable": "1.0.0-alpha.2",
"reflect-metadata": "^0.1.10",
"reflect-metadata": "^0.1.12",
"rxjs": "^6.0.0",
"rxjs-compat": "^6.0.0",
"tslib": "^1.8.0",
"uuid": "^3.1.0"
},
Expand Down Expand Up @@ -84,7 +85,7 @@
"react-hot-loader": "^4.1.2",
"style-loader": "^0.21.0",
"ts-loader": "^4.2.0",
"typescript": "^2.6.1",
"typescript": "^2.8.3",
"uglifyjs-webpack-plugin": "^1.1.0",
"url-loader": "^1.0.1",
"webpack": "^4.6.0",
Expand Down
8 changes: 5 additions & 3 deletions scripts/webpack.client.ts
Original file line number Diff line number Diff line change
Expand Up @@ -98,19 +98,21 @@ const config: any = {

development ? null : new webpack.HashedModuleIdsPlugin(),
development ? null : new webpack.optimize.OccurrenceOrderPlugin(false),
development ? null : new webpack.optimize.CommonsChunkPlugin({ name: 'vendor' }),
development ? null : new webpack.optimize.CommonsChunkPlugin({ name: 'manifest' }),
development ? null : new webpack.optimize.ModuleConcatenationPlugin(),
// development ? null : new webpack.optimize.CommonsChunkPlugin({ name: 'vendor' }), // webpack 4 delete
// development ? null : new webpack.optimize.CommonsChunkPlugin({ name: 'manifest' }), // webpack 4 delete
// development ? null : new webpack.optimize.ModuleConcatenationPlugin(), // webpack 4 defualt exist
development ? null : new BundleAnalyzerPlugin(),
development
? null
// 在 4.x 版本之前,用的是 extract-text-webpack-plugin,不过 [email protected] 不支持使用。
: new Extract({
filename: 'index-[chunkhash:8].css',
disable: false,
allChunks: true
}),
development
? null
// webpack 4 默认提供???
: new Uglify({
uglifyOptions: {
compress: { warnings: false },
Expand Down
13 changes: 8 additions & 5 deletions src/client/@pages/counter/counter.module.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { Observable } from 'rxjs';
import { interval } from 'rxjs';
import { takeUntil, map, delay, switchMap } from 'rxjs/operators';

const INC = `COUNTER/INC`;
const DEC = `COUNTER/DEC`;
Expand Down Expand Up @@ -37,15 +38,17 @@ export const actions = {
}
};

const asyncIncEpic = (action$) => action$.ofType(ASYNC_INC).delay(1000).map(actions.inc);
const asyncIncEpic = (action$) => action$.ofType(ASYNC_INC).pipe(delay(1000), map(actions.inc));

const asyncDecEpic = (action$) => action$.ofType(ASYNC_DEC).delay(1000).map(actions.dec);
const asyncDecEpic = (action$) => action$.ofType(ASYNC_DEC).pipe(delay(1000), map(actions.dec));

const intervalIncEpic = (action$) =>
action$
.ofType(INTERVAL_INC)
.switchMap((e) =>
Observable.interval(1000).takeUntil(action$.ofType(ASYNC_DEC, DEC)).map(actions.inc)
.pipe(
switchMap((e) =>
interval(1000).pipe(takeUntil(action$.ofType(ASYNC_DEC, DEC)), map(actions.inc))
)
);

export const epics = [ asyncIncEpic, asyncDecEpic, intervalIncEpic ];
29 changes: 15 additions & 14 deletions src/client/@pages/counter/index.async.tsx
Original file line number Diff line number Diff line change
@@ -1,24 +1,25 @@
import * as React from 'react';
import { connect } from 'react-redux';
import { injectModule } from '@store';
import * as mod from './counter.module'
import * as mod from './counter.module';

injectModule('counter', mod)
class CounterPage extends React.Component<any, any> {
render() {
return <div>
<h1>{this.props.counter}</h1>
<button onClick={this.props.inc}>inc</button>
<button onClick={this.props.dec}>dec</button>
<button onClick={this.props.asyncInc}>async_inc</button>
<button onClick={this.props.asyncDec}>async_dec</button>
<button onClick={this.props.intervalInc}>interval_inc</button>
</div>
}
injectModule('counter', mod);

function CounterPage(props) {
return (
<div>
<h1>{props.counter}</h1>
<button onClick={props.inc}>inc</button>
<button onClick={props.dec}>dec</button>
<button onClick={props.asyncInc}>async_inc</button>
<button onClick={props.asyncDec}>async_dec</button>
<button onClick={props.intervalInc}>interval_inc</button>
</div>
);
}

function mapStateToProps({ counter }) {
return { counter };
return { counter };
}

export default connect(mapStateToProps, mod.actions)(CounterPage);
20 changes: 12 additions & 8 deletions src/client/@pages/github-users/github-users.module.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { Observable } from 'rxjs';
import { timer } from 'rxjs';
import { fetchSearchUsers } from '@servers/github';
import { mergeMap, map, filter, switchMap } from 'rxjs/operators';

const SEARCH_USERS = `GITHUB-USER/SEARCH_USERS`;
const RECEIVE_USERS = `GITHUB-USER/RECEIVE_USERS`;
Expand Down Expand Up @@ -35,13 +36,16 @@ export const actions = {
const searchUsersEpic = (action$) =>
action$
.ofType(SEARCH_USERS)
.map((act) => act.payload.query)
.filter(Boolean)
.switchMap((q) =>
Observable.timer(800)
.mergeMap(() => fetchSearchUsers(q))
.map((data) => data['items'])
.map(actions.receiveUsers)
.pipe(
map((act: any) => act.payload.query),
filter(Boolean),
switchMap((q) =>
timer(800).pipe(
mergeMap(() => fetchSearchUsers(q)),
map((data) => data['items']),
map(actions.receiveUsers)
)
)
);

export const epics = [ searchUsersEpic ];
2 changes: 1 addition & 1 deletion src/client/@pages/github-users/index.async.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ class GithubUsersPage extends React.Component<any, any> {
<div>
<input onChange={this.handleChange} />
{loading && <h1>loading...</h1>}
{users.map((e) => <h1>{e.login || e}</h1>)}
{users && users.map((e) => <h1>{e.login || e}</h1>)}
</div>
);
}
Expand Down
2 changes: 0 additions & 2 deletions src/client/@store/common/actions.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
import { empty } from 'rxjs/Observer';

export function emptyActon() {
return { type: 'empty-action' };
}
3 changes: 2 additions & 1 deletion src/client/@store/index.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { createStore, applyMiddleware, compose, Store, combineReducers } from 'redux';
import { mergeMap } from 'rxjs/operators';
import { createEpicMiddleware, combineEpics } from 'redux-observable';
import { BehaviorSubject } from 'rxjs/BehaviorSubject';
import modules from './modules';
Expand All @@ -19,7 +20,7 @@ export default function create(data = {}): LifeStore {

// epics middle
let behaviorEpics$ = new BehaviorSubject(rootEpics);
let rootEpics$ = (actions$, store) => behaviorEpics$.mergeMap((epic) => epic(actions$, store, {}));
let rootEpics$ = (actions$, store) => behaviorEpics$.pipe(mergeMap((epic) => epic(actions$, store, {})));
let epicMiddle = createEpicMiddleware(rootEpics$);

// middles & enhancers
Expand Down
127 changes: 65 additions & 62 deletions src/client/@store/modules/auth.ts
Original file line number Diff line number Diff line change
@@ -1,85 +1,88 @@
import { Observable } from 'rxjs';
import { from, of } from 'rxjs';
import { login } from '@servers/auth';
import { compose } from 'redux';
import { emptyActon } from '@store/common/actions';
import { map, catchError, switchMap } from 'rxjs/operators';

const LOGIN = `AUTH/LOGIN`;
const LOGIN_SUCCESS = `AUTH/LOGIN_SUCCESS`;
const LOGIN_FAILD = `AUTH/LOGIN_FAILD`;
const LOGOUT = `AUTH/LOGOUT`;

const init = {
user: {},
logined: false,
logining: false
user: {},
logined: false,
logining: false
};

export function reducer(state = init, action) {
let { type, payload } = action;
switch (type) {
case LOGIN:
return {
...state,
logining: true
};
case LOGIN_SUCCESS:
return {
...state,
...payload,
logined: true,
logining: false
};
case LOGIN_FAILD:
return {
...state,
...payload,
logining: false
};
case LOGOUT:
return init;
default:
return state;
}
let { type, payload } = action;
switch (type) {
case LOGIN:
return {
...state,
logining: true
};
case LOGIN_SUCCESS:
return {
...state,
...payload,
logined: true,
logining: false
};
case LOGIN_FAILD:
return {
...state,
...payload,
logining: false
};
case LOGOUT:
return init;
default:
return state;
}
}

export const actions = {
login(user) {
return { type: LOGIN, payload: { user } };
},
loginSuccess(user) {
return { type: LOGIN_SUCCESS, payload: { user } };
},
loginFaild({ message }) {
return { type: LOGIN_FAILD, payload: { error: message } };
},
logout() {
return { type: LOGOUT };
}
login(user) {
return { type: LOGIN, payload: { user } };
},
loginSuccess(user) {
return { type: LOGIN_SUCCESS, payload: { user } };
},
loginFaild({ message }) {
return { type: LOGIN_FAILD, payload: { error: message } };
},
logout() {
return { type: LOGOUT };
}
};

const effect = {
cacheAuth(user) {
localStorage.auth = JSON.stringify({ user, logined: true });
return user;
},
clearAuth(arg) {
localStorage.removeItem('auth');
return arg;
}
cacheAuth(user) {
localStorage.auth = JSON.stringify({ user, logined: true });
return user;
},
clearAuth(arg) {
localStorage.removeItem('auth');
return arg;
}
};

const loginEpic = (action$, store) =>
action$.ofType(LOGIN).switchMap(act =>
Observable.fromPromise(login(act.payload.user))
.map(effect.cacheAuth)
.map(actions.loginSuccess)
.catch(compose((err: any) => Observable.of(actions.loginFaild(err)), effect.clearAuth))
);
const loginEpic = (action$, store) => {
return action$
.ofType(LOGIN)
.pipe(
switchMap((act: any) =>
from(login(act.payload.user)).pipe(
map(effect.cacheAuth),
map(actions.loginSuccess),
catchError(compose((err: any) => of(actions.loginFaild(err)), effect.clearAuth))
)
)
);
};

const logoutEpic = action$ =>
action$
.ofType(LOGOUT)
.map(effect.clearAuth)
.map(emptyActon);
const logoutEpic = (action$) => action$.ofType(LOGOUT).pipe(map(effect.clearAuth), map(emptyActon));

export const epics = [loginEpic, logoutEpic];
export const epics = [ loginEpic, logoutEpic ];
2 changes: 1 addition & 1 deletion src/server/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ export async function bootstrap(cb = bootstrapBackcall) {
: '../client';
app.use(express.static(path.resolve(__dirname, clientDistRelativePath)));

const nest = await NestFactory.create(ApplicationModule, app);
const nest = await NestFactory.create(ApplicationModule, app, { cors: true });
nest.use(multiparty());
nest.use(bodyParser.urlencoded({ extended: true }));
nest.use(bodyParser.json());
Expand Down
8 changes: 6 additions & 2 deletions yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -4466,7 +4466,7 @@ redux@^3.6.0:
loose-envify "^1.1.0"
symbol-observable "^1.0.3"

reflect-metadata@^0.1.10:
reflect-metadata@^0.1.12:
version "0.1.12"
resolved "http://registry.npm.taobao.org/reflect-metadata/download/reflect-metadata-0.1.12.tgz#311bf0c6b63cd782f228a81abe146a2bfa9c56f2"

Expand Down Expand Up @@ -4620,6 +4620,10 @@ run-queue@^1.0.0, run-queue@^1.0.3:
dependencies:
aproba "^1.1.1"

rxjs-compat@^6.0.0:
version "6.0.0"
resolved "http://registry.npm.taobao.org/rxjs-compat/download/rxjs-compat-6.0.0.tgz#2496403f74042d07899faeeac0bd703e4bce6710"

rxjs@^6.0.0:
version "6.0.0"
resolved "http://registry.npm.taobao.org/rxjs/download/rxjs-6.0.0.tgz#d647e029b5854617f994c82fe57a4c6747b352da"
Expand Down Expand Up @@ -5186,7 +5190,7 @@ typedarray@^0.0.6:
version "0.0.6"
resolved "http://registry.npm.taobao.org/typedarray/download/typedarray-0.0.6.tgz#867ac74e3864187b1d3d47d996a78ec5c8830777"

typescript@*, typescript@^2.6.1:
typescript@*, typescript@^2.8.3:
version "2.8.3"
resolved "http://registry.npm.taobao.org/typescript/download/typescript-2.8.3.tgz#5d817f9b6f31bb871835f4edf0089f21abe6c170"

Expand Down

0 comments on commit 0b47c90

Please sign in to comment.