diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 0000000..c308ed0 --- /dev/null +++ b/.editorconfig @@ -0,0 +1,13 @@ +# http://editorconfig.org +root = true + +[*] +indent_style = space +indent_size = 4 +end_of_line = lf +charset = utf-8 +trim_trailing_whitespace = true +insert_final_newline = true + +[*.md] +trim_trailing_whitespace = false diff --git a/.eslintrc b/.eslintrc new file mode 100644 index 0000000..94df36a --- /dev/null +++ b/.eslintrc @@ -0,0 +1,21 @@ +{ + "plugins": [ + "react" + ], + "ecmaFeatures": { + "jsx": true, + "modules": true + }, + "env": { + "browser": true, + "amd": true, + "es6": true + }, + "rules": { + "quotes": [ 1, "single" ], + "no-undef": false, + "global-strict": false, + "no-extra-semi": 1, + "no-underscore-dangle": false + } +} diff --git a/.gitignore b/.gitignore index 2d39cbd..75015a6 100644 --- a/.gitignore +++ b/.gitignore @@ -1,5 +1,42 @@ -.pid -node_modules -web-starter-kit* -public/bundles -webpack-assets.json +### SublimeText ### +*.sublime-workspace + +### OSX ### +.DS_Store +.AppleDouble +.LSOverride +Icon + +# Thumbnails +._* + +# Files that might appear on external disk +.Spotlight-V100 +.Trashes + +### Windows ### +# Windows image file caches +Thumbs.db +ehthumbs.db + +# Folder config file +Desktop.ini + +# Recycle Bin used on file shares +$RECYCLE.BIN/ + +# App specific + +node_modules/ +.tmp +dist +/src/main.js +/src/images/sprite/*.png +/src/stylesheets/sprite/* +/gowebpackstarter* +webpack*assets.json +webpack*options.json +filerev.json + +# IDEA +.idea diff --git a/.jshintrc b/.jshintrc new file mode 100644 index 0000000..2f22258 --- /dev/null +++ b/.jshintrc @@ -0,0 +1,27 @@ +{ + "node": true, + "browser": true, + "esnext": true, + "bitwise": true, + "camelcase": false, + "curly": true, + "eqeqeq": true, + "immed": true, + "indent": 2, + "latedef": true, + "newcap": true, + "noarg": true, + "quotmark": "false", + "regexp": true, + "undef": true, + "unused": false, + "strict": true, + "trailing": true, + "smarttabs": true, + "white": true, + "newcap": false, + "globals": { + "React": true + } +} + diff --git a/.yo-rc.json b/.yo-rc.json new file mode 100644 index 0000000..a35fa29 --- /dev/null +++ b/.yo-rc.json @@ -0,0 +1,8 @@ +{ + "generator-react-webpack": { + "app-name": "goWebpackStarter", + "architecture": "reflux", + "styles-language": "stylus", + "component-suffix": "js" + } +} \ No newline at end of file diff --git a/AssetsExportPlugin.js b/AssetsExportPlugin.js new file mode 100644 index 0000000..d6f1f92 --- /dev/null +++ b/AssetsExportPlugin.js @@ -0,0 +1,89 @@ +var path = require('path'); +var fs = require('fs'); +var _ = require('lodash'); + + // AssetsExportPlugin Export assets Map + // as: + // ```json + // { + // "a.js": "a-e78567.js", + // "a.css": "a-3b27b7.css", + // "b.js": "b-e78567.js" + // } + // ``` + +var AssetsExportPlugin = function(path){ + this.exportPath = path; + } + + AssetsExportPlugin.prototype = { + + constructor: AssetsExportPlugin, + + apply: function( compiler ) { + var self = this; + + // on `after-emit` Event + // export the map + compiler.plugin('after-emit', function(compilation, callback){ + console.log('webpack after-emit'); + var stats = compilation.getStats().toJson({ + hash: true, + publicPath: true, + assets: true, + chunks: false, + modules: false, + source: false, + errorDetails: false, + timings: false + }); + + var json = {}; + _.forOwn(stats.assetsByChunkName, function(assets, key){ + + // "a" : "a-xxxxx.js" => "a.js" + + function fullName(name, asset){ + return name + path.extname(asset); + } + + // "a": ["a-xxx.js", "a-yyy.css"] + if(_.isArray(assets)){ + _.each(assets, function(asset){ + if(asset.indexOf('.hot-update.')!== -1){ + return ; + } + json[fullName(key, asset)] = asset + }) + + // or "a": "a-xxx.js" + }else{ + + json[fullName(key, assets)] = assets; + } + }) + + // save map to file + + fs.writeFile( + self.exportPath, + JSON.stringify(json, null, 4), + { + encoding: 'utf8', + flag: 'w+' + }, + function(err){ + if(err) { + console.error(err.message); + return; + } + setTimeout(callback, 2000) + } + ); + + }) + } + + }; + +module.exports = AssetsExportPlugin diff --git a/Gruntfile.js b/Gruntfile.js new file mode 100644 index 0000000..5511132 --- /dev/null +++ b/Gruntfile.js @@ -0,0 +1,113 @@ +'use strict'; +var path = require('path'); +var fs = require('fs'); +var _ = require('lodash'); +var chalk= require('chalk'); +var mountFolder = function (connect, dir) { + return connect.static(require('path').resolve(dir)); +}; + + + +module.exports = function (grunt) { + // Let *load-grunt-tasks* require everything + require('load-grunt-tasks')(grunt); + + var saveJSON = function(file, obj){ + grunt.file.write(file, JSON.stringify(obj, null, 4)); + } + + // Read configuration from package.json + var pkgConfig = grunt.file.readJSON('package.json'); + + grunt.initConfig({ + host: '0.0.0.0', + pkg: pkgConfig, + + open: { + options: { + delay: 5000 + }, + dev: { + path: 'http://localhost:<%= pkg.port.backend %>' + }, + dist: { + path: 'http://localhost:<%= pkg.port.backend %>/' + } + }, + + karma: { + unit: { + configFile: 'karma.conf.js' + } + }, + + // copy: { + // dist: { + // files: [ + // // includes files within path + // { + // flatten: true, + // expand: true, + // src: ['<%= pkg.src %>/*'], + // dest: '<%= pkg.dist %>/', + // filter: 'isFile' + // }, + // { + // flatten: true, + // expand: true, + // src: ['<%= pkg.src %>/images/*'], + // dest: '<%= pkg.dist %>/images/' + // } + // ] + // } + // }, + + clean: { + dist: { + files: [{ + src: [ + '<%= pkg.dist %>' + ] + }] + } + }, + + }); + + //load tasks files + grunt.loadTasks('./tasks') + + grunt.registerTask('serve', function (target) { + + if (target === 'dist') { + return grunt.task.run([ + 'build', + 'webpack', + 'open:dist']); + } + + grunt.task.run([ + 'build', + 'server', + 'entry', + 'webpack-dev-server', + 'open:dev', + 'chokidar' + ]); + }); + + + grunt.registerTask('test', ['karma']); + + grunt.registerTask('build', [ + 'clean', + 'spriteInit', 'sprite', + // 'tinypng', + 'filerev', 'filerev.export', 'assetsJSON', + 'shell:goBuild' + ]); + + // grunt.registerTask('build-go', ['shell:goBuild']) + grunt.registerTask('default', []); +}; diff --git a/LICENSE b/LICENSE deleted file mode 100644 index cb76019..0000000 --- a/LICENSE +++ /dev/null @@ -1,21 +0,0 @@ -The MIT License (MIT) - -Copyright (c) 2016 Jia Mi - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. diff --git a/Makefile b/Makefile deleted file mode 100644 index 2df31dd..0000000 --- a/Makefile +++ /dev/null @@ -1,38 +0,0 @@ -IMPORT_PATH = $(shell echo `pwd` | sed "s|^$(GOPATH)/src/||g") -APP_NAME = $(shell echo $(IMPORT_PATH) | sed 's:.*/::') -APP_VERSION = 0.1 -TARGET = ./$(APP_NAME)-$(APP_VERSION) -GO_FILES = $(shell find . -type f -name "*.go") -BUNDLE = public/bundles -ASSETS = $(shell find assets -type f) -PID = .pid -NODE_BIN = $(shell npm bin) - -build: clean $(BUNDLE) $(TARGET) - -clean: - @rm -rf public/bundles - @rm -rf $(TARGET) - -$(BUNDLE): $(ASSETS) - @$(NODE_BIN)/webpack --progress --colors - -$(TARGET): $(GO_FILES) - @printf "Buiding go binary ......" - @go build -race -o $@ - -kill: - @kill `cat $(PID)` || true - -dev: clean $(BUNDLE) restart - @DEV_HOT=true $(NODE_BIN)/webpack-dev-server --config webpack.config.js & - @printf "\n\nWaiting for the file change\n\n" - @fswatch --event=Updated $(GO_FILES) | xargs -n1 -I{} make restart || make kill - -restart: kill $(TARGET) - @printf "\n\nrestart the app .........\n\n" - @$(TARGET) -debug & echo $$! > $(PID) - -dist: clean $(TARGET) - @NODE_ENV=production $(NODE_BIN)/webpack --progress --colors - @zip -r -v $(APP_NAME)-$(APP_VERSION).zip $(TARGET) webpack-assets.json public templates diff --git a/README.md b/README.md deleted file mode 100644 index baefa85..0000000 --- a/README.md +++ /dev/null @@ -1,45 +0,0 @@ -web-starter-kit ------ - -Use Go, Webpack to build and package web application starter kit. - -1. Use sweb to make web server -1. Use webpack to package all the frontend assets -1. Use webpack-dev-server to support HMR -1. Depends on GNU Make and fswatch - -Demo: - -1. Use [material-design-lite](https://getmdl.io) SCSS version as the basic style templates and customize the color and themes -1. Use React to build a MDL Component button -1. run `make dev` to start a local development watcher, auto watch assets change and go code change, restart the go web server -1. run `make dist` to create distribution packages, including all the assets, templates and binary which can be deployed -1. A `DemoApi` controller rendering JSON response -1. A `DemoController` controller rendering HTML response using templates - -Big thanks to: - -1. [go-starter-kit](https://github.com/olebedev/go-starter-kit) -1. [Webpack your bags](http://blog.madewithlove.be/post/webpack-your-bags/) -1. [react-transform-hmr](https://github.com/gaearon/react-transform-hmr) -1. [babel-preset-react-hmre](https://github.com/danmartinez101/babel-preset-react-hmre) - -Hot module reload - -[See webpack-dev-server doc](http://webpack.github.io/docs/webpack-dev-server.html#combining-with-an-existing-server) - -1. `GO Web Server` should render all aseets with prefix the dev-server domain `http://localhost:8000` -1. As config in `webpack.config.js`, all the request (except the hot-update ones ) is proxied to `GO web Server` - -Missing Parts: - -1. Sprite images management and auto-generation -1. Config the port of both **Go Web Server** and **webpack-dev-server**, and config each one for the other - -Contributions: - -1. acecode.tk@gmail.com for the HMR - -License ---- -MIT diff --git a/assets/components/Button.js b/assets/components/Button.js deleted file mode 100644 index cb3a428..0000000 --- a/assets/components/Button.js +++ /dev/null @@ -1,64 +0,0 @@ -import React from 'react'; -import classnames from 'classnames'; -import _ from 'lodash'; - -function mdlUpgrade(Component) { - const MDLComponent = React.createClass({ - componentDidMount() { - componentHandler.upgradeDom(); - }, - componentDidUpdate() { - componentHandler.upgradeDom(); - }, - render() { - return - }, - }); - return MDLComponent; -} - -const Icon = (props) => { - return ({props.name}); -}; - -const ClassedButton = (props) => { - let btnProps = { - className: props.className, - to: props.to, - style: props.style, - onClick: (evt) => props.onClick && props.onClick(evt), - }; - if (props.id) { - btnProps.id = props.id; - } - let children = []; - let toReverse = false; - if (props.icon) { - const alignRight = props.iconAlign === 'right'; - toReverse = alignRight; - let iconStyle = _.assign({}, props.iconStyle); - if (props.title) { - alignRight ? iconStyle['marginLeft'] = 8 : iconStyle['marginRight'] = 8; - } - children.push(); - } - if (props.title) { - children.push({props.title}); - } - if (toReverse) { - children.reverse(); - } - return props.to ? {children} : ; -}; - -const Button = (props) => { - const claz = classnames('mdl-button mdl-js-button mdl-js-ripple-effect', { - 'mdl-button--colored': props.color === 'colored', - 'mdl-button--primary': props.color === 'primary', - 'mdl-button--accent': props.color === 'accent', - 'mdl-button--raised': props.raised === true, - }); - return ; -}; - -export default mdlUpgrade(Button); diff --git a/assets/index.js b/assets/index.js deleted file mode 100644 index 85c4657..0000000 --- a/assets/index.js +++ /dev/null @@ -1,11 +0,0 @@ -import "./stylesheets/base.scss"; -import "material-design-lite"; - -import React from 'react'; -import ReactDom from 'react-dom'; - -import Button from '#coms/Button'; - -ReactDom.render( -