1
0
mirror of https://github.com/ascribe/onion.git synced 2024-12-22 17:33:14 +01:00

Add webpack config

Notable changes:

* Updated to babel 6
* Updated polyfills to only include core-js/es6 and core-js/stage/4
rather than entire babel/polyfill set
* Dev server with hot reloading replaces server.js in development
* Updated bootstrap loading to be separate from app’s stylesheets
* Cleaned up some of the font dependencies, removing the need for
templating their paths
This commit is contained in:
Brett Sun 2016-06-02 15:24:16 +02:00
parent d2a17839ee
commit bd2895afa0
14 changed files with 291 additions and 43 deletions

16
.bootstraprc Normal file
View File

@ -0,0 +1,16 @@
---
bootstrapVersion: 3
# Phase this out, first with react-component's bootstrap overrides, and then nothing at all
preBootstrapCustomizations: ./sass/bootstrap/overrides
styleLoaders:
- style
- css?sourceMap
- postcss
- sass?sourceMap&output=expanded&precision=8
# For now, just include everything from Bootstrap
styles: true
scripts: false

1
.gitignore vendored
View File

@ -18,6 +18,7 @@ results
.env .env
build/* build/*
dist/*
gemini-coverage/* gemini-coverage/*
gemini-report/* gemini-report/*

View File

@ -170,12 +170,11 @@ A: Use `npm dedupe` to remove duplicates in npm. This might fix that you're not
Q: How can I use a local copy of SPOOL and Onion? Q: How can I use a local copy of SPOOL and Onion?
A: Easily by starting the your gulp process with the following command: A: Easily by starting the your gulp process with the following command:
``` ```
ONION_BASE_URL='/' ONION_SERVER_URL='http://localhost.com:8000/' gulp serve ONION_SERVER_URL='http://localhost.com:8000/' gulp serve
``` ```
Or, by adding these two your environment variables: Or, by adding the local server url to your environment variables:
``` ```
ONION_BASE_URL='/'
ONION_SERVER_URL='http://localhost.com:8000/' ONION_SERVER_URL='http://localhost.com:8000/'
``` ```

View File

@ -1,14 +1,14 @@
'use strict'; 'use strict';
import 'babel/polyfill'; import 'core-js/es6';
import 'core-js/stage/4';
import 'classlist-polyfill'; import 'classlist-polyfill';
import 'isomorphic-fetch';
import React from 'react'; import React from 'react';
import { Router, Redirect } from 'react-router'; import { Router, Redirect } from 'react-router';
import history from './history'; import history from './history';
import fetch from 'isomorphic-fetch';
import ApiUrls from './constants/api_urls'; import ApiUrls from './constants/api_urls';
import AppConstants from './constants/application_constants'; import AppConstants from './constants/application_constants';
@ -20,15 +20,20 @@ import { getDefaultSubdomainSettings, getSubdomainSettings } from './utils/const
import { initLogging } from './utils/error_utils'; import { initLogging } from './utils/error_utils';
import { getSubdomain } from './utils/general_utils'; import { getSubdomain } from './utils/general_utils';
// FIXME: redo these event actions
import EventActions from './actions/event_actions'; import EventActions from './actions/event_actions';
// FIXME: use a ./third_party/index.js instead, remove DebugHandler
// You can comment out the modules you don't need // You can comment out the modules you don't need
// import DebugHandler from './third_party/debug_handler'; // import DebugHandler from './third_party/debug_handler';
import FacebookHandler from './third_party/facebook_handler'; import './third_party/facebook_handler';
import GoogleAnalyticsHandler from './third_party/ga_handler'; import './third_party/ga_handler';
import IntercomHandler from './third_party/intercom_handler'; import './third_party/intercom_handler';
import NotificationsHandler from './third_party/notifications_handler'; import './third_party/notifications_handler';
import RavenHandler from './third_party/raven_handler'; import './third_party/raven_handler';
// Import global stylesheet
import '../sass/main.scss';
const AppGateway = { const AppGateway = {

View File

@ -1,7 +1,8 @@
'use strict'; 'use strict';
import React from 'react/addons'; import React from 'react/addons';
import fineUploader from 'fineUploader'; // FIXME: remove once using react-components
import fineUploader from 'exports?qq!./vendor/s3.fine-uploader';
import Q from 'q'; import Q from 'q';
import S3Fetcher from '../../fetchers/s3_fetcher'; import S3Fetcher from '../../fetchers/s3_fetcher';

View File

@ -1,6 +1,7 @@
'use strict'; 'use strict';
import fineUploader from 'fineUploader'; // FIXME: remove once using react-components
import fineUploader from 'exports?qq!./vendor/s3.fine-uploader';
import MimeTypes from '../../constants/mime_types'; import MimeTypes from '../../constants/mime_types';

View File

@ -1,19 +1,13 @@
'use strict'; 'use strict';
//const baseUrl = 'http://localhost:8000/api/'; const apiEndpoint = process.env.API_URL;
const serverUrl = process.env.SERVER_URL;
//FIXME: referring to a global variable in `window` is not const baseUrl = process.env.APP_BASE_PATH;
// super pro. What if we render stuff on the server?
// - super-bro - Senor Developer, 14th July 2015
//const baseUrl = window.BASE_URL;
const apiEndpoint = window.API_ENDPOINT;
const serverUrl = window.SERVER_URL;
const baseUrl = window.BASE_URL;
const constants = { const constants = {
apiEndpoint, apiEndpoint,
serverUrl,
baseUrl, baseUrl,
serverUrl,
'aclList': ['acl_coa', 'acl_consign', 'acl_delete', 'acl_download', 'acl_edit', 'acl_create_editions', 'acl_view_editions', 'aclList': ['acl_coa', 'acl_consign', 'acl_delete', 'acl_download', 'acl_edit', 'acl_create_editions', 'acl_view_editions',
'acl_loan', 'acl_loan_request', 'acl_share', 'acl_transfer', 'acl_unconsign', 'acl_unshare', 'acl_view', 'acl_loan', 'acl_loan_request', 'acl_share', 'acl_transfer', 'acl_unconsign', 'acl_unshare', 'acl_view',
'acl_withdraw_transfer', 'acl_wallet_submit'], 'acl_withdraw_transfer', 'acl_wallet_submit'],

View File

@ -11,11 +11,15 @@
"node": "6.2.0" "node": "6.2.0"
}, },
"scripts": { "scripts": {
"lint": "eslint ./js",
"preinstall": "export SAUCE_CONNECT_DOWNLOAD_ON_INSTALL=true", "preinstall": "export SAUCE_CONNECT_DOWNLOAD_ON_INSTALL=true",
"postinstall": "npm run build", "postinstall": "npm run build",
"build": "", "build": "rimraf ./dist && NODE_ENV=production webpack -p",
"start": "", "start": "NODE_ENV=production node server.js",
"build:dev": "rimraf ./build && NODE_ENV=development webpack",
"clean": "rimraf ./build ./dist",
"start:dev": "NODE_ENV=development node server.dev.js",
"lint": "eslint ./",
"test": "npm run sauce-test", "test": "npm run sauce-test",
"sauce-test": "mocha ./test/integration/tests/", "sauce-test": "mocha ./test/integration/tests/",
@ -45,12 +49,14 @@
"jest-cli": "^0.4.0", "jest-cli": "^0.4.0",
"mocha": "^2.3.4", "mocha": "^2.3.4",
"phantomjs2": "^2.0.2", "phantomjs2": "^2.0.2",
"rimraf": "^2.5.2",
"sauce-connect-launcher": "^0.13.0", "sauce-connect-launcher": "^0.13.0",
"wd": "^0.4.0" "wd": "^0.4.0"
}, },
"dependencies": { "dependencies": {
"alt": "^0.16.5", "alt": "^0.16.5",
"audiojs": "vrde/audiojs", "audiojs": "vrde/audiojs",
"autoprefixer": "^6.3.6",
"babel-cli": "^6.9.0", "babel-cli": "^6.9.0",
"babel-loader": "^6.2.4", "babel-loader": "^6.2.4",
"babel-plugin-react-transform": "^2.0.2", "babel-plugin-react-transform": "^2.0.2",
@ -60,19 +66,29 @@
"babel-plugin-transform-runtime": "^6.9.0", "babel-plugin-transform-runtime": "^6.9.0",
"babel-preset-es2015-no-commonjs": "0.0.2", "babel-preset-es2015-no-commonjs": "0.0.2",
"babel-preset-react": "^6.5.0", "babel-preset-react": "^6.5.0",
"bootstrap-sass": "^3.3.4", "babel-runtime": "^6.9.0",
"bootstrap-loader": "^1.0.10",
"bootstrap-sass": "^3.3.6",
"camelcase": "^1.2.1", "camelcase": "^1.2.1",
"classlist-polyfill": "^1.0.2", "classlist-polyfill": "^1.0.2",
"classnames": "^1.2.2", "classnames": "^1.2.2",
"compression": "^1.6.2", "compression": "^1.6.2",
"core-js": "^2.4.0",
"css-loader": "^0.23.1",
"decamelize": "^1.1.1", "decamelize": "^1.1.1",
"dotenv": "^1.2.0",
"eslint": "^0.22.1", "eslint": "^0.22.1",
"eslint-plugin-react": "^2.5.0", "eslint-plugin-react": "^2.5.0",
"exports-loader": "^0.6.3",
"express": "^4.13.4", "express": "^4.13.4",
"extract-text-webpack-plugin": "^1.0.1",
"file-loader": "^0.8.5",
"history": "1.17.0", "history": "1.17.0",
"invariant": "^2.1.1", "invariant": "^2.1.1",
"isomorphic-fetch": "^2.0.2", "isomorphic-fetch": "^2.0.2",
"moment": "^2.10.6", "moment": "^2.10.6",
"node-sass": "^3.7.0",
"postcss-loader": "^0.9.1",
"q": "^1.4.1", "q": "^1.4.1",
"query-string": "^3.0.0", "query-string": "^3.0.0",
"raven-js": "^1.1.19", "raven-js": "^1.1.19",
@ -84,9 +100,16 @@
"react-star-rating": "~1.3.2", "react-star-rating": "~1.3.2",
"react-textarea-autosize": "^2.5.2", "react-textarea-autosize": "^2.5.2",
"react-transform-hmr": "^1.0.4", "react-transform-hmr": "^1.0.4",
"resolve-url-loader": "^1.4.3",
"sass-loader": "^3.2.0",
"shallow-equals": "0.0.0", "shallow-equals": "0.0.0",
"shmui": "^0.1.0", "shmui": "^0.1.0",
"spark-md5": "~1.0.0" "spark-md5": "~1.0.0",
"style-loader": "^0.13.1",
"url-loader": "^0.5.7",
"webpack": "^2.1.0-beta.7",
"webpack-combine-loaders": "^2.0.0",
"webpack-dev-server": "^2.1.0-beta.0"
}, },
"jest": { "jest": {
"scriptPreprocessor": "node_modules/babel-jest", "scriptPreprocessor": "node_modules/babel-jest",

View File

@ -13,11 +13,11 @@
@font-face { @font-face {
font-family: 'ascribe-font'; font-family: 'ascribe-font';
src:url('#{$BASE_URL}static/fonts/ascribe-font.eot?q6qoae'); src:url('../fonts/ascribe-font.eot?q6qoae');
src:url('#{$BASE_URL}static/fonts/ascribe-font.eot?q6qoae#iefix') format('embedded-opentype'), src:url('../fonts/ascribe-font.eot?q6qoae#iefix') format('embedded-opentype'),
url('#{$BASE_URL}static/fonts/ascribe-font.ttf?q6qoae') format('truetype'), url('../fonts/ascribe-font.ttf?q6qoae') format('truetype'),
url('#{$BASE_URL}static/fonts/ascribe-font.woff?q6qoae') format('woff'), url('../fonts/ascribe-font.woff?q6qoae') format('woff'),
url('#{$BASE_URL}static/fonts/ascribe-font.svg?q6qoae#ascribe-font') format('svg'); url('../fonts/ascribe-font.svg?q6qoae#ascribe-font') format('svg');
font-weight: normal; font-weight: normal;
font-style: normal; font-style: normal;
} }

View File

@ -0,0 +1,2 @@
@import '../ascribe_variables';
@import '../variables';

File diff suppressed because one or more lines are too long

View File

@ -1,12 +1,9 @@
// If you import a new .scss file, make sure to restart gulp // If you import a new .scss file, make sure to restart gulp
// otherwise it will not be included // otherwise it will not be included
$BASE_URL: '<%= BASE_URL %>';
@import 'mixins'; @import 'mixins';
@import 'ascribe_variables'; @import 'ascribe_variables';
@import 'variables'; @import 'variables';
@import '../node_modules/bootstrap-sass/assets/stylesheets/bootstrap';
@import '../node_modules/react-star-rating/dist/css/react-star-rating.min'; @import '../node_modules/react-star-rating/dist/css/react-star-rating.min';
@import '../node_modules/react-datepicker/dist/react-datepicker'; @import '../node_modules/react-datepicker/dist/react-datepicker';
@import 'glyphicons-social'; @import 'glyphicons-social';

46
server.dev.js Normal file
View File

@ -0,0 +1,46 @@
/* eslint-disable strict, no-console */
/* eslint-disable import/no-extraneous-dependencies, import/newline-after-import */
'use strict';
const path = require('path');
const WebpackDevServer = require('webpack-dev-server');
const webpack = require('webpack');
const config = require('./webpack.config.js');
require('dotenv').load({ silent: true });
const HOST = process.env.ONION_DEV_HOST || 'localhost';
const PORT = process.env.ONION_DEV_PORT || 3000;
// Enable server hot reloading
// React hot reloading is enabled through .babelrc and babel-react-transform
config.entry.unshift(`webpack-dev-server/client?http://${HOST}:${PORT}/`,
'webpack/hot/dev-server');
config.plugins.push(new webpack.HotModuleReplacementPlugin());
// Specify output location for bundled files
config.output.publicPath = '/static/';
// Configure server
const compiler = webpack(config);
const server = new WebpackDevServer(compiler, {
publicPath: config.output.publicPath,
contentBase: './build',
historyApiFallback: {
index: config.output.publicPath
},
hot: true,
stats: { colors: true }
});
// Start server
server.listen(PORT, HOST, (err) => {
if (err) {
console.error(`Onion dev server ran into ${err} while starting on ${HOST}:${PORT} ` +
`with basePath set to ${BASE_PATH || '/'}. Shutting down...`);
server.close();
}
console.log(`Onion server running on ${HOST}:${PORT} with basePath set to ${BASE_PATH || '/'}.`);
});

163
webpack.config.js Normal file
View File

@ -0,0 +1,163 @@
/* eslint-disable strict, no-console, object-shorthand */
/* eslint-disable import/no-extraneous-dependencies, import/newline-after-import */
'use strict';
const path = require('path');
const webpack = require('webpack');
const autoPrefixer = require('autoprefixer');
const combineLoaders = require('webpack-combine-loaders');
const ExtractTextPlugin = require('extract-text-webpack-plugin');
require('dotenv').load({ silent: true });
const PRODUCTION = process.env.NODE_ENV === 'production';
const PATHS = {
APP: path.resolve(__dirname, 'js/app.js'),
BUILD: path.resolve(__dirname, 'build'),
DIST: path.resolve(__dirname, 'dist'),
NODE_MODULES: path.resolve(__dirname, 'node_modules'),
};
/** EXTERNAL DEFINITIONS INJECTED INTO APP **/
const DEFINITIONS = {
'process.env': {
NODE_ENV: JSON.stringify(process.env.NODE_ENV || 'development'),
};
/** PLUGINS **/
const PLUGINS = [
new webpack.DefinePlugin(DEFINITIONS),
new webpack.NoErrorsPlugin(),
// Extract stylesheets out of bundle
new ExtractTextPlugin(
PRODUCTION ? 'css/styles.min.css' : 'css/styles.css', {
allChunks: true
}
),
const PROD_PLUGINS = [
new webpack.optimize.UglifyJsPlugin({
compress: {
warnings: false
},
output: {
comments: false
}
}),
new webpack.LoaderOptionsPlugin({
debug: false,
minimize: true
}),
];
if (PRODUCTION) {
PLUGINS.push(...PROD_PLUGINS);
}
/** LOADERS **/
const JS_LOADER = combineLoaders([
{
loader: 'babel',
query: {
cacheDirectory: true,
},
},
]);
const CSS_LOADER = combineLoaders([
{
loader: 'css',
query: {
sourceMap: true,
},
},
{ loader: 'postcss' },
]);
const SASS_LOADER = `${CSS_LOADER}!` + combineLoaders([
{
loader: 'sass',
query: {
precision: '8', // See https://github.com/twbs/bootstrap-sass#sass-number-precision
outputStyle: 'expanded',
sourceMap: true,
},
}
]);
const URL_FONT_LOADER = combineLoaders([
{
loader: 'url',
query: {
limit: 10000,
name: 'fonts/[name].[ext]',
},
},
]);
const FILE_FONT_LOADER = combineLoaders([
{
loader: 'file',
query: {
name: 'fonts/[name].[ext]',
},
},
]);
const LOADERS = [
{
test: /\.jsx?$/,
exclude: [PATHS.NODE_MODULES],
loader: JS_LOADER,
},
{
test: /\.s[ac]ss$/,
exclude: [PATHS.NODE_MODULES],
loader: ExtractTextPlugin.extract('style', SASS_LOADER),
},
// Fonts
// woffs and svgs are typically smaller should we can try to load them as a url
{
test: /\.(woff2?|svg)$/,
loader: URL_FONT_LOADER,
},
{
test: /\.(ttf|eot)$/,
loader: FILE_FONT_LOADER,
},
];
/** EXPORTED WEBPACK CONFIG **/
const config = {
entry: ['bootstrap-loader/extractStyles', PATHS.APP],
output: {
filename: PRODUCTION ? 'js/bundle.min.js' : 'js/bundle.js',
path: PRODUCTION ? PATHS.DIST : PATHS.BUILD,
},
debug: !PRODUCTION,
devtool: PRODUCTION ? '#source-map' : '#inline-source-map',
resolve: {
extensions: ['', '.js', '.jsx'],
modules: ['node_modules'], // Don't use absolute path here to allow recursive matching
},
plugins: PLUGINS,
module: {
loaders: LOADERS,
},
postcss: [autoPrefixer()],
};
module.exports = config;