diff --git a/Makefile b/Makefile index 0ce9e7c1d..32ee566f4 100644 --- a/Makefile +++ b/Makefile @@ -50,17 +50,18 @@ $(SCOPE_EXPORT): $(SCOPE_EXE) $(DOCKER_DISTRIB) docker/weave $(RUNSVINIT) docker $(RUNSVINIT): vendor/runsvinit/*.go -$(SCOPE_EXE): $(shell find ./ -path ./vendor -prune -o -type f -name *.go) prog/static.go $(CODECGEN_TARGETS) +$(SCOPE_EXE): $(shell find ./ -path ./vendor -prune -o -type f -name *.go) prog/staticui/staticui.go prog/externalui/externalui.go $(CODECGEN_TARGETS) report/report.codecgen.go: $(call GET_CODECGEN_DEPS,report/) render/render.codecgen.go: $(call GET_CODECGEN_DEPS,render/) render/detailed/detailed.codecgen.go: $(call GET_CODECGEN_DEPS,render/detailed/) -static: prog/static.go -prog/static.go: client/build/app.js +static: prog/staticui/staticui.go prog/externalui/externalui.go +prog/staticui/staticui.go: client/build/index.html +prog/externalui/externalui.go: client/build-external/index.html ifeq ($(BUILD_IN_CONTAINER),true) -$(SCOPE_EXE) $(RUNSVINIT) lint tests shell prog/static.go: $(SCOPE_BACKEND_BUILD_UPTODATE) +$(SCOPE_EXE) $(RUNSVINIT) lint tests shell prog/staticui/staticui.go prog/externalui/externalui.go: $(SCOPE_BACKEND_BUILD_UPTODATE) @mkdir -p $(shell pwd)/.pkg $(SUDO) docker run $(RM) $(RUN_FLAGS) \ -v $(shell pwd):/go/src/github.com/weaveworks/scope \ @@ -104,19 +105,30 @@ lint: $(SCOPE_BACKEND_BUILD_UPTODATE) ./tools/lint -ignorespelling "agre " -ignorespelling "AGRE " . ./tools/shell-lint tools -prog/static.go: $(SCOPE_BACKEND_BUILD_UPTODATE) - esc -o $@ -prefix client/build client/build +prog/staticui/staticui.go: $(SCOPE_BACKEND_BUILD_UPTODATE) + mkdir -p prog/staticui + esc -o $@ -pkg staticui -prefix client/build client/build + +prog/externalui/externalui.go: $(SCOPE_BACKEND_BUILD_UPTODATE) + mkdir -p prog/externalui + esc -o $@ -pkg externalui -prefix client/build-external -include '.*\.htm' client/build-external endif ifeq ($(BUILD_IN_CONTAINER),true) -client/build/app.js: $(shell find client/app -type f) $(SCOPE_UI_BUILD_UPTODATE) +client/build/index.html: $(shell find client/app -type f) $(SCOPE_UI_BUILD_UPTODATE) mkdir -p client/build $(SUDO) docker run $(RM) $(RUN_FLAGS) -v $(shell pwd)/client/app:/home/weave/app \ -v $(shell pwd)/client/build:/home/weave/build \ $(SCOPE_UI_BUILD_IMAGE) npm run build +client/build-external/index.html: $(shell find client/app -type f) $(SCOPE_UI_BUILD_UPTODATE) + mkdir -p client/build + $(SUDO) docker run $(RM) $(RUN_FLAGS) -v $(shell pwd)/client/app:/home/weave/app \ + -v $(shell pwd)/client/build:/home/weave/build \ + $(SCOPE_UI_BUILD_IMAGE) npm run build-external + client-test: $(shell find client/app/scripts -type f) $(SCOPE_UI_BUILD_UPTODATE) $(SUDO) docker run $(RM) $(RUN_FLAGS) -v $(shell pwd)/client/app:/home/weave/app \ -v $(shell pwd)/client/test:/home/weave/test \ @@ -134,9 +146,12 @@ client-start: $(SCOPE_UI_BUILD_UPTODATE) else -client/build/app.js: +client/build/index.html: cd client && npm run build +client/build-external/index.html: + cd client && npm run build-external + endif $(SCOPE_UI_BUILD_UPTODATE): client/Dockerfile client/package.json client/webpack.local.config.js client/webpack.production.config.js client/server.js client/.eslintrc diff --git a/circle.yml b/circle.yml index eabc320e5..24a641848 100644 --- a/circle.yml +++ b/circle.yml @@ -30,6 +30,7 @@ dependencies: - "cd $SRCDIR/backend; ../tools/rebuild-image weaveworks/scope-backend-build . Dockerfile build.sh && touch $SRCDIR/.scope_backend_build.uptodate" - test -z "$SECRET_PASSWORD" || (cd $SRCDIR/integration; ./gce.sh make_template): parallel: false + - sudo apt-get update && sudo apt-get install python-pip && sudo pip install awscli: test: override: diff --git a/client/Dockerfile b/client/Dockerfile index d120de18c..7438af7d8 100644 --- a/client/Dockerfile +++ b/client/Dockerfile @@ -3,4 +3,4 @@ WORKDIR /home/weave COPY package.json /home/weave/ ENV NPM_CONFIG_LOGLEVEL=warn NPM_CONFIG_PROGRESS=false RUN npm install -COPY webpack.local.config.js webpack.production.config.js server.js .babelrc .eslintrc .eslintignore /home/weave/ +COPY webpack.local.config.js webpack.production.config.js webpack.external.config.js server.js .babelrc .eslintrc .eslintignore /home/weave/ diff --git a/client/package.json b/client/package.json index 207f383e1..650e59ccb 100644 --- a/client/package.json +++ b/client/package.json @@ -77,6 +77,7 @@ }, "scripts": { "build": "webpack --config webpack.production.config.js", + "build-external": "webpack --config webpack.external.config.js", "start": "node server.js", "start-production": "NODE_ENV=production node server.js", "test": "jest", diff --git a/client/webpack.external.config.js b/client/webpack.external.config.js new file mode 100644 index 000000000..92e610290 --- /dev/null +++ b/client/webpack.external.config.js @@ -0,0 +1,121 @@ +var webpack = require('webpack'); +var autoprefixer = require('autoprefixer'); +var path = require('path'); + +var CleanWebpackPlugin = require('clean-webpack-plugin'); +var ExtractTextPlugin = require("extract-text-webpack-plugin"); +var HtmlWebpackPlugin = require('html-webpack-plugin'); + +var GLOBALS = { + 'process.env': {NODE_ENV: '"production"'} +}; + +/** + * This is the Webpack configuration file for hosting most of the static content + * (all but index.htm) on an external host (eg. a CDN). + * You should change output.publicPath to point to your external host. + */ +module.exports = { + + // fail on first error when building release + bail: true, + + cache: {}, + + entry: { + app: './app/scripts/main', + 'contrast-app': './app/scripts/contrast-main', + 'terminal-app': './app/scripts/terminal-main', + // keep only some in here, to make vendors and app bundles roughly same size + vendors: ['babel-polyfill', 'classnames', 'd3', 'immutable', + 'lodash', 'react', 'react-dom', 'react-redux', + 'redux', 'redux-thunk'] + }, + + output: { + path: path.join(__dirname, 'build-external/'), + filename: '[name]-[chunkhash].js', + // Change this line to point to resources on an external host. + publicPath: 'https://s3.amazonaws.com/static.weave.works/service-ui/' + }, + + module: { + include: [ + path.resolve(__dirname, 'app/scripts') + ], + preLoaders: [ + { + test: /\.js$/, + exclude: /node_modules|vendor/, + loader: 'eslint-loader' + } + ], + loaders: [ + { + test: /\.less$/, + loader: ExtractTextPlugin.extract('style-loader', + 'css-loader?minimize!postcss-loader!less-loader') + }, + { + test: /\.woff(2)?(\?v=[0-9]\.[0-9]\.[0-9])?$/, + loader: 'url-loader?limit=10000&minetype=application/font-woff' + }, + { + test: /\.(ttf|eot|svg|ico)(\?v=[0-9]\.[0-9]\.[0-9])?$/, + loader: 'file-loader' + }, + { + test: /\.ico$/, + loader: 'file-loader?name=[name].[ext]' + }, + { test: /\.jsx?$/, exclude: /node_modules|vendor/, loader: 'babel' } + ] + }, + + postcss: [ + autoprefixer({ + browsers: ['last 2 versions'] + }) + ], + + eslint: { + failOnError: true + }, + + resolve: { + extensions: ['', '.js', '.jsx'] + }, + + plugins: [ + new CleanWebpackPlugin(['build']), + new webpack.DefinePlugin(GLOBALS), + new webpack.optimize.CommonsChunkPlugin('vendors', 'vendors-[chunkhash].js'), + new webpack.optimize.OccurenceOrderPlugin(true), + new webpack.IgnorePlugin(/^\.\/locale$/, [/moment$/]), + new webpack.optimize.UglifyJsPlugin({ + sourceMap: false, + compress: { + warnings: false + } + }), + new ExtractTextPlugin('style-[name]-[chunkhash].css'), + new HtmlWebpackPlugin({ + hash: true, + chunks: ['vendors', 'contrast-app'], + template: 'app/html/index.html', + filename: 'contrast.html' + }), + new HtmlWebpackPlugin({ + hash: true, + chunks: ['vendors', 'terminal-app'], + template: 'app/html/index.html', + filename: 'terminal.html' + }), + new HtmlWebpackPlugin({ + hash: true, + chunks: ['vendors', 'app'], + template: 'app/html/index.html', + filename: 'index.html' + }) + ] +}; diff --git a/client/webpack.production.config.js b/client/webpack.production.config.js index 21ad03ef0..beb31633e 100644 --- a/client/webpack.production.config.js +++ b/client/webpack.production.config.js @@ -32,7 +32,7 @@ module.exports = { output: { path: path.join(__dirname, 'build/'), - filename: '[name].js' + filename: '[name]-[chunkhash].js', }, module: { @@ -85,7 +85,7 @@ module.exports = { plugins: [ new CleanWebpackPlugin(['build']), new webpack.DefinePlugin(GLOBALS), - new webpack.optimize.CommonsChunkPlugin('vendors', 'vendors.js'), + new webpack.optimize.CommonsChunkPlugin('vendors', 'vendors-[chunkhash].js'), new webpack.optimize.OccurenceOrderPlugin(true), new webpack.IgnorePlugin(/^\.\/locale$/, [/moment$/]), new webpack.optimize.UglifyJsPlugin({ @@ -94,7 +94,7 @@ module.exports = { warnings: false } }), - new ExtractTextPlugin('style-[name].css'), + new ExtractTextPlugin('style-[name]-[chunkhash].css'), new HtmlWebpackPlugin({ hash: true, chunks: ['vendors', 'contrast-app'], diff --git a/prog/app.go b/prog/app.go index a33f7c1ec..76213b4cf 100644 --- a/prog/app.go +++ b/prog/app.go @@ -59,7 +59,7 @@ func router(collector app.Collector, controlRouter app.ControlRouter, pipeRouter app.RegisterPipeRoutes(router, pipeRouter) app.RegisterTopologyRoutes(router, collector) - uiHandler := http.FileServer(FS(false)) + uiHandler := http.FileServer(GetFS(false)) router.PathPrefix("/ui").Name("static").Handler( middleware.PathRewrite(regexp.MustCompile("^/ui"), "").Wrap( uiHandler)) diff --git a/prog/static.go b/prog/static.go new file mode 100644 index 000000000..68261afbb --- /dev/null +++ b/prog/static.go @@ -0,0 +1,16 @@ +package main + +import ( + "net/http" + + "github.com/weaveworks/scope/prog/staticui" + "github.com/weaveworks/scope/prog/externalui" +) + +func GetFS(use_external bool) http.FileSystem { + if use_external { + return externalui.FS(false) + } else { + return staticui.FS(false) + } +}