hauler 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/.babelrc +1 -0
- data/.eslintrc +5 -1
- data/.gitignore +1 -0
- data/.nvmrc +1 -0
- data/Makefile +6 -1
- data/bin/dev-server.js +6 -4
- data/bin/read-config.js +15 -0
- data/bin/update-scripts.js +1 -1
- data/lib/generators/hauler/install_generator.rb +5 -1
- data/lib/generators/hauler/install_npm_generator.rb +1 -0
- data/lib/generators/hauler/templates/config/hauler.js +9 -5
- data/lib/generators/hauler/templates/config/initializers/hauler.rb +1 -0
- data/lib/generators/hauler/templates/eslintrc.json +1 -3
- data/lib/generators/hauler/templates/webpack.config.js +4 -3
- data/lib/hauler/helpers/hauler_helper.rb +76 -0
- data/lib/hauler/railtie.rb +11 -18
- data/lib/hauler/version.rb +6 -1
- data/lib/hauler.rb +3 -0
- data/make-package.js +11 -1
- data/package.json +24 -9
- data/src/decls/hauler.js +7 -0
- data/src/decls/webpack.js +16 -11
- data/src/defaults/compiler_config_factory.js +5 -96
- data/src/defaults/dev_server_config_factory.js +3 -4
- data/src/defaults/project_config_factory.js +109 -0
- data/src/index.js +25 -104
- data/src/utils/__tests__/extract_config-test.js +132 -0
- data/src/utils/__tests__/merge_config-test.js +75 -0
- data/src/utils/__tests__/path-test.js +26 -0
- data/src/utils/extract_config.js +103 -0
- data/src/utils/index.js +6 -0
- data/src/utils/merge_config.js +34 -0
- data/src/utils/misc.js +61 -0
- data/src/utils/path.js +73 -0
- data/wallaby.js +20 -0
- metadata +16 -4
- data/lib/hauler/asset_tag_helper.rb +0 -27
- data/src/utils.js +0 -103
@@ -0,0 +1,109 @@
|
|
1
|
+
// @flow
|
2
|
+
|
3
|
+
import ExtractTextPlugin from 'extract-text-webpack-plugin';
|
4
|
+
import * as webpack from 'webpack';
|
5
|
+
|
6
|
+
import devServerConfigFactory from './dev_server_config_factory';
|
7
|
+
import compilerConfigFactory from './compiler_config_factory';
|
8
|
+
|
9
|
+
function getPlugins(env: string) {
|
10
|
+
let plugins = [
|
11
|
+
new webpack.ProvidePlugin({ fetch: 'exports?self.fetch!whatwg-fetch' }),
|
12
|
+
new webpack.DefinePlugin({ 'process.env': { NODE_ENV: JSON.stringify(env) } }),
|
13
|
+
new webpack.optimize.CommonsChunkPlugin({
|
14
|
+
name: 'vendor',
|
15
|
+
children: true,
|
16
|
+
minChunks: 2,
|
17
|
+
async: true,
|
18
|
+
}),
|
19
|
+
];
|
20
|
+
|
21
|
+
if (env === 'development') {
|
22
|
+
plugins = plugins.concat([
|
23
|
+
new webpack.NoErrorsPlugin(),
|
24
|
+
]);
|
25
|
+
}
|
26
|
+
|
27
|
+
if (env === 'production') {
|
28
|
+
plugins = plugins.concat([
|
29
|
+
new webpack.optimize.OccurrenceOrderPlugin(true),
|
30
|
+
new webpack.optimize.DedupePlugin(),
|
31
|
+
new webpack.optimize.UglifyJsPlugin({ compress: { warnings: false } }),
|
32
|
+
new ExtractTextPlugin('[name].[contenthash].css'),
|
33
|
+
]);
|
34
|
+
}
|
35
|
+
|
36
|
+
return plugins;
|
37
|
+
}
|
38
|
+
|
39
|
+
function configFactory(env: string) {
|
40
|
+
const entries = {};
|
41
|
+
|
42
|
+
// individual loaders so that they can be replaced separately
|
43
|
+
const javascriptLoader = {
|
44
|
+
test: /\.jsx?$/,
|
45
|
+
loader: 'babel',
|
46
|
+
exclude: /node_modules/,
|
47
|
+
query: {
|
48
|
+
presets: ['es2015', 'react', 'stage-2'],
|
49
|
+
plugins: ['transform-class-properties'],
|
50
|
+
},
|
51
|
+
};
|
52
|
+
|
53
|
+
const sassLoader = {
|
54
|
+
test: /\.scss$/,
|
55
|
+
loader: 'style!css!sass',
|
56
|
+
};
|
57
|
+
|
58
|
+
const fontLoader = {
|
59
|
+
test: /\.(eot|svg|ttf|woff|woff2)$/,
|
60
|
+
loader: 'file',
|
61
|
+
};
|
62
|
+
|
63
|
+
const imageLoader = {
|
64
|
+
test: /\.(jpg|png|gif)$/,
|
65
|
+
loaders: [
|
66
|
+
'file',
|
67
|
+
'image-webpack?{progressive:true, optimizationLevel: 7, interlaced: false, pngquant:{quality: "65-90", speed: 4}}',
|
68
|
+
],
|
69
|
+
};
|
70
|
+
|
71
|
+
if (env === 'production') {
|
72
|
+
javascriptLoader.query.plugins = javascriptLoader.query.plugins.concat([
|
73
|
+
'transform-react-remove-prop-types',
|
74
|
+
'transform-react-constant-elements',
|
75
|
+
'transform-react-inline-elements',
|
76
|
+
]);
|
77
|
+
|
78
|
+
sassLoader.loader = ExtractTextPlugin.extract(
|
79
|
+
'style',
|
80
|
+
sassLoader.loader.replace('style!', '')
|
81
|
+
);
|
82
|
+
}
|
83
|
+
|
84
|
+
const appendPlugins = [];
|
85
|
+
const plugins = getPlugins(env);
|
86
|
+
const prependPlugins = [];
|
87
|
+
|
88
|
+
const publicPath = '/assets';
|
89
|
+
|
90
|
+
const devServer = devServerConfigFactory(env);
|
91
|
+
|
92
|
+
const compiler = compilerConfigFactory(env);
|
93
|
+
|
94
|
+
return {
|
95
|
+
entries,
|
96
|
+
javascriptLoader,
|
97
|
+
sassLoader,
|
98
|
+
fontLoader,
|
99
|
+
imageLoader,
|
100
|
+
prependPlugins,
|
101
|
+
plugins,
|
102
|
+
appendPlugins,
|
103
|
+
publicPath,
|
104
|
+
devServer,
|
105
|
+
compiler,
|
106
|
+
};
|
107
|
+
}
|
108
|
+
|
109
|
+
export default configFactory;
|
data/src/index.js
CHANGED
@@ -1,122 +1,43 @@
|
|
1
1
|
// @flow
|
2
|
-
// NOTE: This code is executed in a Gem, which makes any npm package unavailable
|
3
2
|
|
4
|
-
|
5
|
-
const devServerDefaultsFactory = require('./defaults/dev_server_config_factory');
|
6
|
-
const utils = require('./utils');
|
3
|
+
import * as utils from './utils';
|
7
4
|
|
8
|
-
function
|
9
|
-
|
10
|
-
|
11
|
-
config.sassLoader,
|
12
|
-
config.fontLoader,
|
13
|
-
config.imageLoader,
|
14
|
-
]);
|
5
|
+
function getProjectConfig(env: string): ProjectConfig {
|
6
|
+
const projectConfigFactory = require(utils.railsPath('~config/hauler.js'));
|
7
|
+
return projectConfigFactory(env);
|
15
8
|
}
|
16
9
|
|
17
|
-
function
|
18
|
-
const
|
19
|
-
|
20
|
-
return utils.deepMerge(resolve, { modules: utils.railsPath(modules) });
|
10
|
+
function getProjectDefaults(env: string): ProjectConfig {
|
11
|
+
const projectDefaultsFactory = require('./defaults/project_config_factory');
|
12
|
+
return projectDefaultsFactory.default(env);
|
21
13
|
}
|
22
14
|
|
23
|
-
function
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
function extractModule(config: ProjectConfig): WebpackModuleConfig {
|
31
|
-
const module = config.compiler && config.compiler.module;
|
32
|
-
return utils.deepMerge(module, {
|
33
|
-
loaders: extractLoaders(config),
|
34
|
-
});
|
35
|
-
}
|
36
|
-
|
37
|
-
function extractOutput(config: ProjectConfig): WebpackOutputConfig {
|
38
|
-
const output = config.compiler && config.compiler.output || {};
|
39
|
-
const path = output.path || '';
|
40
|
-
return utils.deepMerge(output, {
|
41
|
-
path: utils.railsPath(path),
|
42
|
-
});
|
43
|
-
}
|
44
|
-
|
45
|
-
function parseToCompilerConfig(config: ProjectConfig): WebpackConfig {
|
46
|
-
return {
|
47
|
-
entry: utils.railsPath(config.entries),
|
48
|
-
output: extractOutput(config),
|
49
|
-
module: extractModule(config),
|
50
|
-
plugins: extractPlugins(config),
|
51
|
-
resolve: extractResolve(config),
|
15
|
+
function getConfigFactory(): ProjectConfigFactory {
|
16
|
+
return (env: string) => {
|
17
|
+
const projectDefaults = getProjectDefaults(env);
|
18
|
+
const projectConfig = getProjectConfig(env);
|
19
|
+
const config = utils.mergeProjectConfig(projectDefaults, projectConfig);
|
20
|
+
return config;
|
52
21
|
};
|
53
22
|
}
|
54
23
|
|
55
|
-
function
|
56
|
-
|
57
|
-
|
58
|
-
return '';
|
24
|
+
export function getConfig(env: string, railsRoot?: string) {
|
25
|
+
if (railsRoot != null) {
|
26
|
+
utils.setRailsRoot(railsRoot);
|
59
27
|
}
|
60
28
|
|
61
|
-
|
62
|
-
|
63
|
-
}
|
64
|
-
|
65
|
-
const host = config.host || 'localhost';
|
66
|
-
const port = config.port || 30001;
|
67
|
-
return `http://${host}:${port}/${publicPath.replace(/^\//, '')}`;
|
68
|
-
}
|
69
|
-
|
70
|
-
function prepareDevServerConfig(config: WebpackDevServerConfig): WebpackDevServerConfig {
|
71
|
-
const output = Object.assign({}, config, {
|
72
|
-
publicPath: extractPublicPath(config),
|
73
|
-
});
|
74
|
-
|
75
|
-
return output;
|
29
|
+
const configFactory = getConfigFactory();
|
30
|
+
return configFactory(env);
|
76
31
|
}
|
77
32
|
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
* Returns a factory for getting the project webpack dev server configuration using the
|
82
|
-
* value of the `devServer` property in the result of `{Rails.root}/config/hauler.js`
|
83
|
-
*/
|
84
|
-
function webpackDevServerConfigFactory(defaultsFactory: DevServerConfigFactory) {
|
85
|
-
return (env: string): WebpackDevServerConfig => {
|
86
|
-
const defaultDevServerConfig = defaultsFactory(env);
|
87
|
-
const projectDevServerConfig = projectConfig.devServer;
|
88
|
-
const devServerConfig = utils.deepMerge(defaultDevServerConfig, projectDevServerConfig);
|
89
|
-
return prepareDevServerConfig(devServerConfig);
|
90
|
-
};
|
33
|
+
export function getDevServerConfig(env: string, railsRoot?: string): WebpackDevServerConfig {
|
34
|
+
const config = getConfig(env, railsRoot);
|
35
|
+
return utils.extractDevServerConfig(config);
|
91
36
|
}
|
92
37
|
|
93
|
-
function
|
94
|
-
|
95
|
-
|
96
|
-
const haulerProjectConfig = utils.deepMerge(defaultProjectConfig, projectConfig);
|
97
|
-
const webpackConfig = parseToCompilerConfig(haulerProjectConfig);
|
98
|
-
return utils.deepMerge(webpackConfig, projectConfig.compiler || {});
|
99
|
-
};
|
38
|
+
export function getCompilerConfig(env: string, railsRoot?: string): WebpackConfig {
|
39
|
+
const config = getConfig(env, railsRoot);
|
40
|
+
return utils.extractCompilerConfig(config);
|
100
41
|
}
|
101
42
|
|
102
|
-
|
103
|
-
getCompilerConfigFactory() {
|
104
|
-
return webpackCompilerConfigFactory(compilerDefaultsFactory);
|
105
|
-
},
|
106
|
-
|
107
|
-
getCompilerConfig(env: string) {
|
108
|
-
const configFactory = Hauler.getCompilerConfigFactory();
|
109
|
-
return configFactory(env);
|
110
|
-
},
|
111
|
-
|
112
|
-
getDevServerConfig(env: string) {
|
113
|
-
const configFactory = Hauler.getDevServerConfigFactory();
|
114
|
-
return configFactory(env);
|
115
|
-
},
|
116
|
-
|
117
|
-
getDevServerConfigFactory() {
|
118
|
-
return webpackDevServerConfigFactory(devServerDefaultsFactory);
|
119
|
-
},
|
120
|
-
};
|
121
|
-
|
122
|
-
module.exports = Hauler;
|
43
|
+
export { getEnvName } from './utils';
|
@@ -0,0 +1,132 @@
|
|
1
|
+
jest.disableAutomock();
|
2
|
+
|
3
|
+
const utils = require('../extract_config');
|
4
|
+
const pathUtils = require('../path');
|
5
|
+
|
6
|
+
describe('extractDevServerConfig', () => {
|
7
|
+
let projectConfigFactory;
|
8
|
+
let projectConfig;
|
9
|
+
|
10
|
+
beforeEach(() => {
|
11
|
+
projectConfigFactory = require('../../defaults/project_config_factory').default;
|
12
|
+
projectConfig = projectConfigFactory('development');
|
13
|
+
});
|
14
|
+
|
15
|
+
describe('contentBase', () => {
|
16
|
+
it('resolves to railsRoot', () => {
|
17
|
+
pathUtils.setRailsRoot('/var/www/hauler');
|
18
|
+
projectConfig.devServer.contentBase = '~lib/assets';
|
19
|
+
const config = utils.extractDevServerConfig(projectConfig);
|
20
|
+
expect(config.contentBase).toBe('/var/www/hauler/lib/assets');
|
21
|
+
});
|
22
|
+
});
|
23
|
+
|
24
|
+
describe('publicPath', () => {
|
25
|
+
it('defaults to http://localhost:3001/assets', () => {
|
26
|
+
const config = utils.extractDevServerConfig({});
|
27
|
+
expect(config.publicPath).toBe('http://localhost:3001/assets');
|
28
|
+
});
|
29
|
+
|
30
|
+
it('leaves a full URL intact', () => {
|
31
|
+
Object.assign(projectConfig.devServer, { host: 'hauler.test', port: 8080 });
|
32
|
+
projectConfig.publicPath = 'https://my.hauler.test:4005/my-assets';
|
33
|
+
const config = utils.extractDevServerConfig(projectConfig);
|
34
|
+
expect(config.publicPath).toBe('https://my.hauler.test:4005/my-assets');
|
35
|
+
});
|
36
|
+
|
37
|
+
it('updates to a full URL', () => {
|
38
|
+
Object.assign(projectConfig.devServer, { host: 'hauler.test', port: 8080 });
|
39
|
+
projectConfig.publicPath = '/my-assets';
|
40
|
+
const config = utils.extractDevServerConfig(projectConfig);
|
41
|
+
expect(config.publicPath).toBe('http://hauler.test:8080/my-assets');
|
42
|
+
});
|
43
|
+
|
44
|
+
it('sets the protocol according to the port', () => {
|
45
|
+
Object.assign(projectConfig.devServer, { port: 80 });
|
46
|
+
let config = utils.extractDevServerConfig(projectConfig);
|
47
|
+
expect(config.publicPath).toMatch('^http://localhost/');
|
48
|
+
|
49
|
+
Object.assign(projectConfig.devServer, { port: 443 });
|
50
|
+
config = utils.extractDevServerConfig(projectConfig);
|
51
|
+
expect(config.publicPath).toMatch('^https://localhost/');
|
52
|
+
});
|
53
|
+
});
|
54
|
+
});
|
55
|
+
|
56
|
+
describe('extractCompilerConfig', () => {
|
57
|
+
let projectConfigFactory;
|
58
|
+
let projectConfig;
|
59
|
+
|
60
|
+
beforeEach(() => {
|
61
|
+
pathUtils.setRailsRoot('/var/www/hauler');
|
62
|
+
projectConfigFactory = require('../../defaults/project_config_factory').default;
|
63
|
+
projectConfig = projectConfigFactory('development');
|
64
|
+
});
|
65
|
+
|
66
|
+
it('resolves #context to railsRoot', () => {
|
67
|
+
projectConfig.compiler.context = '~';
|
68
|
+
const config = utils.extractCompilerConfig(projectConfig);
|
69
|
+
expect(config.context).toBe('/var/www/hauler/');
|
70
|
+
});
|
71
|
+
|
72
|
+
it('assigns projectConfig#entries to #entry', () => {
|
73
|
+
projectConfig.entries = { main: 'main.js' };
|
74
|
+
const config = utils.extractCompilerConfig(projectConfig);
|
75
|
+
expect(config.entry).toEqual({ main: 'main.js' });
|
76
|
+
});
|
77
|
+
|
78
|
+
it('resolves #entry to railsRoot', () => {
|
79
|
+
projectConfig.entries = { main: '~lib/assets/hauler/main.js', counter: './counter' };
|
80
|
+
const config = utils.extractCompilerConfig(projectConfig);
|
81
|
+
expect(config.entry).toEqual({
|
82
|
+
main: '/var/www/hauler/lib/assets/hauler/main.js',
|
83
|
+
counter: './counter',
|
84
|
+
});
|
85
|
+
});
|
86
|
+
|
87
|
+
it('resolves #output.path to railsRoot', () => {
|
88
|
+
projectConfig.compiler.output.path = '~public/assets';
|
89
|
+
const config = utils.extractCompilerConfig(projectConfig);
|
90
|
+
expect(config.output.path).toBe('/var/www/hauler/public/assets');
|
91
|
+
});
|
92
|
+
|
93
|
+
it('resolves #output.publicPath to a full Url using the devServer', () => {
|
94
|
+
projectConfig.publicPath = '/test-assets';
|
95
|
+
Object.assign(projectConfig.devServer, { host: 'asset-host', port: 4005 });
|
96
|
+
const config = utils.extractCompilerConfig(projectConfig);
|
97
|
+
expect(config.output.publicPath).toBe('http://asset-host:4005/test-assets');
|
98
|
+
});
|
99
|
+
|
100
|
+
describe('#module.loaders', () => {
|
101
|
+
it('extracts the loaders from the project config', () => {
|
102
|
+
Object.assign(projectConfig, {
|
103
|
+
javascriptLoader: 'js',
|
104
|
+
sassLoader: 'sass',
|
105
|
+
fontLoader: 'font',
|
106
|
+
imageLoader: 'image',
|
107
|
+
});
|
108
|
+
const config = utils.extractCompilerConfig(projectConfig);
|
109
|
+
expect(config.module.loaders).toEqual(['js', 'sass', 'font', 'image']);
|
110
|
+
});
|
111
|
+
|
112
|
+
it('removes blank loaders', () => {
|
113
|
+
Object.assign(projectConfig, {
|
114
|
+
javascriptLoader: 'js',
|
115
|
+
sassLoader: null,
|
116
|
+
fontLoader: null,
|
117
|
+
imageLoader: 'image',
|
118
|
+
});
|
119
|
+
const config = utils.extractCompilerConfig(projectConfig);
|
120
|
+
expect(config.module.loaders).toEqual(['js', 'image']);
|
121
|
+
});
|
122
|
+
|
123
|
+
it('appends loaders in #compiler.module.loaders', () => {
|
124
|
+
Object.assign(projectConfig, {
|
125
|
+
javascriptLoader: 'js', sassLoader: null, fontLoader: null, imageLoader: null,
|
126
|
+
});
|
127
|
+
projectConfig.module = { loaders: ['other'] };
|
128
|
+
const config = utils.extractCompilerConfig(projectConfig);
|
129
|
+
expect(config.module.loaders).toEqual(['js', 'other']);
|
130
|
+
});
|
131
|
+
});
|
132
|
+
});
|
@@ -0,0 +1,75 @@
|
|
1
|
+
jest.unmock('../merge_config');
|
2
|
+
|
3
|
+
const defaults = {
|
4
|
+
entries: { main: 'my-main-entry.js' },
|
5
|
+
javascriptLoader: { test: 'jsLoader' },
|
6
|
+
sassLoader: { test: 'sassLoader' },
|
7
|
+
fontLoader: { test: 'fontLoader' },
|
8
|
+
imageLoader: { test: 'imageLoader' },
|
9
|
+
prependPlugins: ['prepend'],
|
10
|
+
plugins: ['plugins'],
|
11
|
+
appendPlugins: ['append'],
|
12
|
+
publicPath: '/my-assets',
|
13
|
+
devServer: {
|
14
|
+
stats: { colors: true },
|
15
|
+
},
|
16
|
+
compiler: {
|
17
|
+
output: { filename: '[name]-[hash].js' },
|
18
|
+
module: { loaders: [{ test: /\.js$/ }] },
|
19
|
+
resolve: { alias: { xyz: '/absolute/path/to/file.js' } },
|
20
|
+
},
|
21
|
+
};
|
22
|
+
|
23
|
+
describe('mergeProjectConfig', () => {
|
24
|
+
let misc;
|
25
|
+
let utils;
|
26
|
+
|
27
|
+
beforeEach(() => {
|
28
|
+
misc = require('../misc');
|
29
|
+
misc.merge.mockReturnValue({});
|
30
|
+
|
31
|
+
utils = require('../merge_config');
|
32
|
+
});
|
33
|
+
|
34
|
+
it('merges the source into the defaults', () => {
|
35
|
+
const source = { entries: { main: 'application.js' } };
|
36
|
+
utils.mergeProjectConfig(defaults, source);
|
37
|
+
expect(misc.merge).toBeCalledWith(defaults, source);
|
38
|
+
});
|
39
|
+
|
40
|
+
it('merges the source.devServer into the defaults.devServer', () => {
|
41
|
+
const devServer = { contentBase: '/', quiet: true };
|
42
|
+
utils.mergeProjectConfig(defaults, { devServer });
|
43
|
+
expect(misc.merge).toBeCalledWith(defaults.devServer, devServer);
|
44
|
+
});
|
45
|
+
|
46
|
+
it('merges the source.devServer.stats into the defaults.devServer.stats', () => {
|
47
|
+
const stats = { hash: true };
|
48
|
+
utils.mergeProjectConfig(defaults, { devServer: { stats } });
|
49
|
+
expect(misc.merge).toBeCalledWith(defaults.devServer.stats, stats);
|
50
|
+
});
|
51
|
+
|
52
|
+
it('merges the source.compiler into the defaults.compiler', () => {
|
53
|
+
const compiler = { context: '/', cache: false };
|
54
|
+
utils.mergeProjectConfig(defaults, { compiler });
|
55
|
+
expect(misc.merge).toBeCalledWith(defaults.compiler, compiler);
|
56
|
+
});
|
57
|
+
|
58
|
+
it('merges the source.compiler.output into the defaults.compiler.output', () => {
|
59
|
+
const output = { filename: '[name].js', chunkFilename: '[name].chunk.js' };
|
60
|
+
utils.mergeProjectConfig(defaults, { compiler: { output } });
|
61
|
+
expect(misc.merge).toBeCalledWith(defaults.compiler.output, output);
|
62
|
+
});
|
63
|
+
|
64
|
+
it('merges the source.compiler.module into the defaults.compiler.module', () => {
|
65
|
+
const module = { loaders: [{ test: /\.css$/ }] };
|
66
|
+
utils.mergeProjectConfig(defaults, { compiler: { module } });
|
67
|
+
expect(misc.merge).toBeCalledWith(defaults.compiler.module, module);
|
68
|
+
});
|
69
|
+
|
70
|
+
it('merges the source.compiler.resolve into the defaults.compiler.resolve', () => {
|
71
|
+
const resolve = { alias: { xyz: './dir' } };
|
72
|
+
utils.mergeProjectConfig(defaults, { compiler: { resolve } });
|
73
|
+
expect(misc.merge).toBeCalledWith(defaults.compiler.resolve, resolve);
|
74
|
+
});
|
75
|
+
});
|
@@ -0,0 +1,26 @@
|
|
1
|
+
jest.unmock('../path');
|
2
|
+
|
3
|
+
const utils = require('../path');
|
4
|
+
|
5
|
+
describe('pathJoin', () => {
|
6
|
+
it('leaves the leading slash on the first piece', () => {
|
7
|
+
expect(utils.pathJoin('/hello', 'world')).toBe('/hello/world');
|
8
|
+
expect(utils.pathJoin('hello', 'world')).toBe('hello/world');
|
9
|
+
});
|
10
|
+
|
11
|
+
it('cleans any lagging slash', () => {
|
12
|
+
expect(utils.pathJoin('hello', 'world/')).toBe('hello/world');
|
13
|
+
});
|
14
|
+
|
15
|
+
it('removes any leading or lagging spaces', () => {
|
16
|
+
expect(utils.pathJoin(' hello ', ' world ')).toBe('hello/world');
|
17
|
+
});
|
18
|
+
|
19
|
+
it('removes duplicate slashes', () => {
|
20
|
+
expect(utils.pathJoin('hello///', '///world///')).toBe('hello/world');
|
21
|
+
});
|
22
|
+
|
23
|
+
it('ignores null pieces', () => {
|
24
|
+
expect(utils.pathJoin(null, 'hello', null, 'world', null)).toBe('hello/world');
|
25
|
+
});
|
26
|
+
});
|
@@ -0,0 +1,103 @@
|
|
1
|
+
// @flow
|
2
|
+
|
3
|
+
import url from 'url';
|
4
|
+
import { railsPath } from './path';
|
5
|
+
import { compact } from './misc';
|
6
|
+
|
7
|
+
function resolveValuesRailsPath(entries: Object = {}): Object {
|
8
|
+
const keys = Object.keys(entries);
|
9
|
+
const reducer = (output, key) => Object.assign(output, { [key]: railsPath(entries[key]) });
|
10
|
+
return keys.reduce(reducer, {});
|
11
|
+
}
|
12
|
+
|
13
|
+
function extractLoaders(config: ProjectConfig): Array<WebpackLoader> {
|
14
|
+
const baseLoaders = compact([
|
15
|
+
config.javascriptLoader,
|
16
|
+
config.sassLoader,
|
17
|
+
config.fontLoader,
|
18
|
+
config.imageLoader,
|
19
|
+
]);
|
20
|
+
|
21
|
+
const customLoaders = config.module && config.module.loaders || [];
|
22
|
+
return baseLoaders.concat(customLoaders);
|
23
|
+
}
|
24
|
+
|
25
|
+
function extractResolve(config: ProjectConfig): WebpackResolveConfig {
|
26
|
+
const resolveConfig = config.compiler && config.compiler.resolve || {};
|
27
|
+
return Object.assign(resolveConfig, {
|
28
|
+
alias: resolveValuesRailsPath(resolveConfig.alias),
|
29
|
+
root: railsPath(resolveConfig.root),
|
30
|
+
});
|
31
|
+
}
|
32
|
+
|
33
|
+
function extractPlugins(config: ProjectConfig): Array<WebpackPlugin> {
|
34
|
+
const prepend = config.prependPlugins || [];
|
35
|
+
const plugins = config.plugins || [];
|
36
|
+
const appendPlugins = config.appendPlugins || [];
|
37
|
+
return prepend.concat(plugins).concat(appendPlugins);
|
38
|
+
}
|
39
|
+
|
40
|
+
function extractModule(config: ProjectConfig): WebpackModuleConfig {
|
41
|
+
const moduleConfig = config.compiler && config.compiler.module || {};
|
42
|
+
return Object.assign(moduleConfig, {
|
43
|
+
loaders: extractLoaders(config),
|
44
|
+
});
|
45
|
+
}
|
46
|
+
|
47
|
+
function formatUrl(urlObject: Object) {
|
48
|
+
return url.format(urlObject);
|
49
|
+
}
|
50
|
+
|
51
|
+
function extractPublicPath(config: ProjectConfig): string {
|
52
|
+
const pathUrl = url.parse(config.publicPath || '/assets');
|
53
|
+
const port = String(config.devServer && config.devServer.port || '3001');
|
54
|
+
|
55
|
+
if (!pathUrl.protocol) {
|
56
|
+
pathUrl.protocol = port === '443' ? 'https' : 'http';
|
57
|
+
}
|
58
|
+
|
59
|
+
if (!pathUrl.hostname) {
|
60
|
+
pathUrl.hostname = config.devServer && config.devServer.host || 'localhost';
|
61
|
+
}
|
62
|
+
|
63
|
+
if (!pathUrl.port && port !== '80' && port !== '443') {
|
64
|
+
pathUrl.port = port;
|
65
|
+
}
|
66
|
+
|
67
|
+
return formatUrl(pathUrl);
|
68
|
+
}
|
69
|
+
|
70
|
+
function extractOutput(config: ProjectConfig): WebpackOutputConfig {
|
71
|
+
const outputConfig = config.compiler && config.compiler.output || {};
|
72
|
+
return Object.assign(outputConfig, {
|
73
|
+
path: railsPath(outputConfig.path),
|
74
|
+
publicPath: extractPublicPath(config),
|
75
|
+
});
|
76
|
+
}
|
77
|
+
|
78
|
+
function resolveContentBase(contentBase?: string): ?string {
|
79
|
+
if (!contentBase) {
|
80
|
+
return undefined;
|
81
|
+
}
|
82
|
+
|
83
|
+
return railsPath(contentBase);
|
84
|
+
}
|
85
|
+
|
86
|
+
export function extractCompilerConfig(config: ProjectConfig): WebpackConfig {
|
87
|
+
const compilerConfig = Object.assign({}, config.compiler);
|
88
|
+
return Object.assign({}, compilerConfig, {
|
89
|
+
context: railsPath(compilerConfig.context),
|
90
|
+
entry: resolveValuesRailsPath(config.entries),
|
91
|
+
output: extractOutput(config),
|
92
|
+
module: extractModule(config),
|
93
|
+
resolve: extractResolve(config),
|
94
|
+
plugins: extractPlugins(config),
|
95
|
+
});
|
96
|
+
}
|
97
|
+
|
98
|
+
export function extractDevServerConfig(config: ProjectConfig): WebpackDevServerConfig {
|
99
|
+
return Object.assign({}, config.devServer, {
|
100
|
+
contentBase: resolveContentBase(config.devServer && config.devServer.contentBase),
|
101
|
+
publicPath: extractPublicPath(config),
|
102
|
+
});
|
103
|
+
}
|
data/src/utils/index.js
ADDED
@@ -0,0 +1,34 @@
|
|
1
|
+
// @flow
|
2
|
+
|
3
|
+
import * as misc from './misc';
|
4
|
+
|
5
|
+
function mergeCompilerConfig(
|
6
|
+
target: WebpackConfig = {},
|
7
|
+
source: WebpackConfig = {}
|
8
|
+
): WebpackConfig {
|
9
|
+
const output = misc.merge(target, source);
|
10
|
+
return Object.assign(output, {
|
11
|
+
output: misc.merge(target.output, source.output),
|
12
|
+
module: misc.merge(target.module, source.module),
|
13
|
+
resolve: misc.merge(target.resolve, source.resolve),
|
14
|
+
});
|
15
|
+
}
|
16
|
+
|
17
|
+
function mergeDevServerConfig(
|
18
|
+
target: WebpackDevServerConfig = {},
|
19
|
+
source: WebpackDevServerConfig = {}
|
20
|
+
): WebpackDevServerConfig {
|
21
|
+
const output = misc.merge(target, source);
|
22
|
+
return Object.assign(output, {
|
23
|
+
stats: misc.merge(target.stats, source.stats),
|
24
|
+
});
|
25
|
+
}
|
26
|
+
|
27
|
+
export function mergeProjectConfig(target: ProjectConfig, source: ProjectConfig): ProjectConfig {
|
28
|
+
const output = misc.merge(target, source);
|
29
|
+
return Object.assign(output, {
|
30
|
+
entries: source.entries || target.entries || {},
|
31
|
+
devServer: mergeDevServerConfig(target.devServer, source.devServer),
|
32
|
+
compiler: mergeCompilerConfig(target.compiler, source.compiler),
|
33
|
+
});
|
34
|
+
}
|