Skip to content

Commit 4c57ffd

Browse files
committed
feat: use module-alias over app-module-path; use symbol-aliased paths (@, $) for less confusion
1 parent 2759f6c commit 4c57ffd

File tree

22 files changed

+94
-79
lines changed

22 files changed

+94
-79
lines changed

README.md

+24
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,30 @@ If using Heroku, simply add a `Procfile` in the root directory. The
7171
web: npm run serve
7272
```
7373

74+
## Path Aliases
75+
76+
In `package.json`, there is a property named `_moduleAliases`. This object
77+
defines the require() aliases used by both webpack and node.
78+
79+
Aliased paths are prefixed with one of two symbols, which denote different
80+
things:
81+
82+
`@` - paths in the `common/` folder, e.g. `@components` or `@actions`, etc.
83+
`$` - paths in the `server/` folder
84+
85+
Aliases are nice to use for convenience, and lets us avoid using relative paths
86+
in our components:
87+
88+
```
89+
// This sucks
90+
import SomeComponent from '../../../components/SomeComponent';
91+
92+
// This is way better
93+
import SomeComponent from '@components/SomeComponent';
94+
```
95+
96+
You can add additional aliases in `package.json` to your own liking.
97+
7498
## Environment Variables
7599

76100
In development mode, environment variables are loaded by `dotenv` off the `.env`

client/index.js

+2-2
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,8 @@ import ReactDOM from 'react-dom';
55
import { Provider } from 'react-redux';
66
import { ConnectedRouter } from 'react-router-redux';
77
import createHistory from 'history/createBrowserHistory';
8-
import configureStore from 'store';
9-
import App from 'containers/App';
8+
import configureStore from '@store';
9+
import App from '@containers/App';
1010
import Loadable from 'react-loadable';
1111

1212
// Hydrate the redux store from server state.

client/styles.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -2,4 +2,4 @@
22
import 'semantic-ui-css/semantic.min.css';
33

44
// Base styles
5-
import 'css/base/index.scss';
5+
import '@css/base/index.scss';

common/js/actions/todos.js

+3-3
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,9 @@ import {
55
FETCH_TODOS_REQUEST,
66
FETCH_TODOS_SUCCESS,
77
FETCH_TODOS_FAILURE
8-
} from 'constants/index';
9-
import api from 'lib/api';
10-
import generateActionCreator from 'lib/generateActionCreator';
8+
} from '@constants/index';
9+
import api from '@lib/api';
10+
import generateActionCreator from '@lib/generateActionCreator';
1111

1212
export const addTodo = generateActionCreator(ADD_TODO, 'text');
1313
export const removeTodo = generateActionCreator(REMOVE_TODO, 'id');

common/js/components/todos/TodoList/index.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import React from 'react';
22
import PropTypes from 'prop-types';
33
import { List } from 'semantic-ui-react';
4-
import { TodoItem } from 'components/todos';
4+
import { TodoItem } from '@components/todos';
55
import classnames from 'classnames';
66
import css from './index.scss';
77

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
import React from 'react';
2+
import ReactDOM from 'react-dom';
3+
import TodoList from './index';
4+
5+
describe('TodoList', () => {
6+
it('renders without crashing', () => {
7+
const div = document.createElement('div');
8+
ReactDOM.render(<TodoList />, div);
9+
});
10+
});

common/js/containers/App/index.js

+2-3
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,9 @@
11
import React from 'react';
22
import { Switch } from 'react-router-dom';
3-
import { RouteWithSubRoutes } from 'components/common';
43
import { Container } from 'semantic-ui-react';
5-
import { Header, Footer } from 'components/common';
4+
import { Header, Footer, RouteWithSubRoutes } from '@components/common';
65
import { hot } from 'react-hot-loader';
7-
import routes from 'routes';
6+
import routes from '@routes';
87

98
const App = () => (
109
<Container fluid={false}>

common/js/containers/Todos/index.js

+2-2
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,9 @@ import React, { Component } from 'react';
22
import PropTypes from 'prop-types';
33
import { connect } from 'react-redux';
44
import { Helmet } from 'react-helmet';
5-
import * as actions from 'actions/todos';
5+
import * as actions from '@actions/todos';
66
import { Container } from 'semantic-ui-react';
7-
import { TodoList, TodoForm } from 'components/todos';
7+
import { TodoList, TodoForm } from '@components/todos';
88

99
class TodosContainer extends Component {
1010
static propTypes = {

common/js/pages/Todos/index.js

+3-3
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
11
import React, { Component } from 'react';
22
import Loadable from 'react-loadable';
3-
import { Loading } from 'components/common';
4-
import { fetchTodos } from 'actions/todos';
3+
import { Loading } from '@components/common';
4+
import { fetchTodos } from '@actions/todos';
55

66
// NOTE: To turn off dynamic imports, import this container normally using:
7-
// import TodosContainer from 'containers/Todos';
7+
// import TodosContainer from '@containers/Todos';
88
const TodosContainer = Loadable({
99
loader: () => import('../../containers/Todos'),
1010
loading: Loading

common/js/reducers/todos.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import {
22
ADD_TODO, REMOVE_TODO, TOGGLE_TODO,
33
FETCH_TODOS_REQUEST, FETCH_TODOS_SUCCESS, FETCH_TODOS_FAILURE
4-
} from 'constants/index';
4+
} from '@constants/index';
55

66
const defaultState = {
77
todos: [],

common/js/routes/index.js

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
'use strict';
22

3-
import Home from 'pages/Home';
4-
import Todos from 'pages/Todos';
3+
import Home from '@pages/Home';
4+
import Todos from '@pages/Todos';
55

66
export default [
77
{

common/js/store/index.dev.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import { compose, createStore, applyMiddleware } from 'redux';
22
import thunk from 'redux-thunk';
3-
import rootReducer from 'reducers';
3+
import rootReducer from '@reducers';
44
import { createLogger } from 'redux-logger';
55
import { routerMiddleware } from 'react-router-redux';
66

common/js/store/index.prod.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import { compose, createStore, applyMiddleware } from 'redux';
22
import thunk from 'redux-thunk';
3-
import rootReducer from 'reducers';
3+
import rootReducer from '@reducers';
44
import { routerMiddleware } from 'react-router-redux';
55

66
export default function configureStore(initialState, history = null) {

config/index.js

+1-31
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
12
module.exports = {
23
// Enable or disable server-side rendering
34
enableSSR: true,
@@ -19,37 +20,6 @@ module.exports = {
1920
*/
2021
cssModulesIdentifier: '[name]__[local]__[hash:base64:5]',
2122

22-
/* Paths for webpack to resolve into non-relative directories, so that instead
23-
* of having to use relative paths:
24-
*
25-
* import SomeComponents from '../../../../SomeComponent';
26-
*
27-
* we can write this instead:
28-
*
29-
* import SomeComponent from 'components/SomeComponent';
30-
*/
31-
clientResolvePaths: {
32-
actions: 'common/js/actions',
33-
components: 'common/js/components',
34-
constants: 'common/js/constants',
35-
containers: 'common/js/containers',
36-
css: 'common/css',
37-
fonts: 'common/fonts',
38-
images: 'common/images',
39-
lib: 'common/js/lib',
40-
pages: 'common/js/pages',
41-
reducers: 'common/js/reducers',
42-
routes: 'common/js/routes',
43-
store: 'common/js/store',
44-
templates: 'common/templates'
45-
},
46-
47-
serverResolvePaths: {
48-
api: 'server/api',
49-
constants: 'common/js/constants',
50-
middleware: 'server/middleware'
51-
},
52-
5323
// Isomorphic configuration
5424
isomorphicConfig: {
5525
assets: {

package-lock.json

+5-5
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

+21-1
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,26 @@
3636
"syntax-dynamic-import"
3737
]
3838
},
39+
"_moduleAliases": {
40+
"@css": "common/css",
41+
"@fonts": "common/fonts",
42+
"@images": "common/images",
43+
"@actions": "common/js/actions",
44+
"@components": "common/js/components",
45+
"@constants": "common/js/constants",
46+
"@containers": "common/js/containers",
47+
"@lib": "common/js/lib",
48+
"@middleware": "common/js/middleware",
49+
"@pages": "common/js/pages",
50+
"@reducers": "common/js/reducers",
51+
"@routes": "common/js/routes",
52+
"@store": "common/js/store",
53+
"$api": "server/api",
54+
"$lib": "server/lib",
55+
"$middleware": "server/middleware",
56+
"$templates": "server/templates",
57+
"$config": "config"
58+
},
3959
"scripts": {
4060
"start": "better-npm-run dev:start",
4161
"prod": "better-npm-run prod:build && better-npm-run serve",
@@ -187,7 +207,6 @@
187207
"yn": "^2.0.0"
188208
},
189209
"dependencies": {
190-
"app-module-path": "^2.2.0",
191210
"axios": "^0.17.1",
192211
"body-parser": "^1.18.2",
193212
"chokidar": "^2.0.0",
@@ -201,6 +220,7 @@
201220
"history": "^4.7.2",
202221
"include-media": "^1.4.9",
203222
"lodash": "^4.17.4",
223+
"module-alias": "^2.0.6",
204224
"react": "^16.2.0",
205225
"react-dom": "^16.2.0",
206226
"react-helmet": "^5.2.0",

server/index.js

+4-14
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,13 @@
1+
// Register the `_moduleAliases` as defined in package.json.
2+
require('module-alias/register');
3+
14
const fs = require('fs');
25
const path = require('path');
3-
const config = require('../config');
6+
const config = require('$config');
47
const env = process.env.NODE_ENV || 'development';
5-
const { addPath } = require('app-module-path');
68
const Loadable = require('react-loadable');
79
const chokidar = require('chokidar');
810

9-
global.__basedir = path.join(__dirname, '..');
10-
11-
// Lets us access module paths inside this server directory.
12-
addPath(path.join(__dirname));
13-
14-
// Adds common/js to the app module path so we can access local modules without
15-
// having to use relative paths on the server-side. This is done on the client
16-
// side using webpack's `resolve`.
17-
addPath(path.join(__dirname, '../server'));
18-
addPath(path.join(__dirname, '../common'));
19-
addPath(path.join(__dirname, '../common/js'));
20-
2111
// HTML files are read as pure strings
2212
require.extensions['.html'] = (module, filename) => {
2313
module.exports = fs.readFileSync(filename, 'utf8');

server/lib/.gitkeep

Whitespace-only changes.

server/renderer/handler.js

+4-4
Original file line numberDiff line numberDiff line change
@@ -3,13 +3,13 @@ import { Provider } from 'react-redux';
33
import { StaticRouter, matchPath } from 'react-router';
44
import { setMobileDetect, mobileParser } from 'react-responsive-redux';
55
import { renderToString } from 'react-dom/server';
6-
import { ErrorPage } from 'components/common';
6+
import { ErrorPage } from '@components/common';
77
import { getBundles } from 'react-loadable/webpack';
88
import Loadable from 'react-loadable';
99
import render from './render';
10-
import routes from 'routes';
11-
import configureStore from 'store';
12-
import App from 'containers/App';
10+
import routes from '@routes';
11+
import configureStore from '@store';
12+
import App from '@containers/App';
1313
import config from '../../config';
1414

1515
let stats = null;

server/renderer/render.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ import { template } from 'lodash';
33
import { Helmet } from 'react-helmet';
44

55
const { NODE_ENV } = process.env;
6-
const compile = template(require('templates/layouts/application.html'));
6+
const compile = template(require('$templates/layouts/application.html'));
77
const env = NODE_ENV || 'development';
88

99
export default function render(html, initialState = {}, bundles = []) {

server/server.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ import compression from 'compression';
55
import Api from './api';
66
import cookieParser from 'cookie-parser';
77
import ReactRenderer from './renderer';
8-
import { httpsRedirect } from 'middleware';
8+
import { httpsRedirect } from '$middleware';
99

1010
const env = process.env.NODE_ENV || 'development';
1111
const app = new express();

webpack/base.js

+4-2
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,10 @@ import ExtractTextPlugin from 'extract-text-webpack-plugin';
99
import { BundleAnalyzerPlugin } from 'webpack-bundle-analyzer';
1010
import { ReactLoadablePlugin } from 'react-loadable/webpack';
1111
import { mapValues, keyBy } from 'lodash';
12+
import { _moduleAliases } from '../package.json';
1213
import config from '../config';
1314

15+
let cwd = process.cwd();
1416
let ssr = yn(process.env.SSR) || false;
1517
let isoPlugin = new IsoPlugin(config.isomorphicConfig).development(isDev);
1618
let extractTextPlugin = new ExtractTextPlugin({
@@ -57,8 +59,8 @@ export default {
5759
output,
5860
resolve: {
5961
extensions: ['.js', '.jsx', '.scss'],
60-
alias: mapValues(config.clientResolvePaths, str =>
61-
path.join(process.cwd(), ...str.split('/'))
62+
alias: mapValues(_moduleAliases, aliasPath =>
63+
path.join(cwd, ...aliasPath.split('/'))
6264
)
6365
},
6466
module: {

0 commit comments

Comments
 (0)