├── static ├── style │ ├── common │ │ └── reset.scss │ ├── components │ │ └── tab.scss │ └── modules │ │ └── moduleA.scss └── js │ ├── common │ ├── utils │ │ └── Platform.js │ └── ui │ │ └── Header.js │ ├── app.js │ └── modules │ └── moduleA.js ├── server ├── sql │ └── create.sql ├── js │ ├── controller │ │ └── pageController.js │ ├── dao │ │ ├── urlExtendsDao.js │ │ └── db.js │ ├── service │ │ └── browserService.js │ └── common │ │ └── comRes.js └── views │ └── index.ejs ├── README.md ├── profiles ├── beta │ └── config.json ├── prod │ └── config.json └── dev │ └── config.json ├── app.js ├── .gitignore ├── LICENSE ├── tools └── makeFekitVerPlugin.js ├── package.json ├── gulpfile.js ├── webpack.libs.js ├── webpack.dev.config.js └── webpack.config.js /static/style/common/reset.scss: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /server/sql/create.sql: -------------------------------------------------------------------------------- 1 | /** 2 | * 初始化所有数据表 3 | */ -------------------------------------------------------------------------------- /static/js/common/utils/Platform.js: -------------------------------------------------------------------------------- 1 | /** 2 | * 平台 3 | */ 4 | 5 | module.exports = {}; -------------------------------------------------------------------------------- /static/style/components/tab.scss: -------------------------------------------------------------------------------- 1 | @charset "utf-8"; 2 | 3 | h1 { 4 | font-size: 14px; 5 | color: #333; 6 | } -------------------------------------------------------------------------------- /static/style/modules/moduleA.scss: -------------------------------------------------------------------------------- 1 | @charset "utf-8"; 2 | 3 | @import "../components/tab.scss"; 4 | 5 | body { 6 | background: #ccc; 7 | } -------------------------------------------------------------------------------- /static/js/app.js: -------------------------------------------------------------------------------- 1 | import 'style/modules/moduleA.scss'; 2 | import moduleA from './modules/moduleA'; 3 | 4 | ReactDOM.render(( 5 | 6 | ), document.querySelectorAll('.main')[0]); 7 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ###local dev environment 2 | python --version 2.5 ~ 3.0 3 | ###project initialize 4 | npm run init 5 | ###run project 6 | one command window run: gulp dev 7 | another command window run: node app.js 8 | -------------------------------------------------------------------------------- /server/js/controller/pageController.js: -------------------------------------------------------------------------------- 1 | /** 2 | * 页面入口的 3 | */ 4 | var config = require('../../../resource/config.json'); 5 | var qzzUrl = config.qzzUrl; 6 | 7 | 8 | module.exports = { 9 | homepage: function(req, res) { 10 | res.render('index', { qzzUrl: qzzUrl }); 11 | res.end(""); 12 | } 13 | }; -------------------------------------------------------------------------------- /server/views/index.ejs: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | gulp-webpack-node 6 | 7 | 8 | 9 |
10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /server/js/dao/urlExtendsDao.js: -------------------------------------------------------------------------------- 1 | /** 2 | * 对应 url_host 表 3 | */ 4 | 5 | // var mysql = require("mysql"); 6 | var db = require('./common/db.js'); 7 | // var Promise = require('promise'); 8 | 9 | module.exports = { 10 | 11 | listAll: function() { 12 | var sql = 'SELECT id FROM tableA'; 13 | return db.execSQL(sql); 14 | } 15 | 16 | }; -------------------------------------------------------------------------------- /profiles/beta/config.json: -------------------------------------------------------------------------------- 1 | { 2 | "env": "beta", 3 | 4 | "mysql": { 5 | "host" : "localhost", 6 | "user" : "root", 7 | "password" : "root", 8 | "database" : "testdb", 9 | "port" : 3306, 10 | "writeLog" : false 11 | }, 12 | 13 | "feUrl": "", 14 | 15 | "devServerUrl": "http://127.0.0.1:8888", 16 | 17 | "appRun": 8888 18 | } 19 | -------------------------------------------------------------------------------- /profiles/prod/config.json: -------------------------------------------------------------------------------- 1 | { 2 | "env": "prod", 3 | 4 | "mysql": { 5 | "host" : "localhost", 6 | "user" : "root", 7 | "password" : "root", 8 | "database" : "testdb", 9 | "port" : 3306, 10 | "writeLog" : false 11 | }, 12 | 13 | "feUrl": "", 14 | 15 | "devServerUrl": "http://127.0.0.1:8888", 16 | 17 | "appRun": 8888 18 | } 19 | -------------------------------------------------------------------------------- /static/js/modules/moduleA.js: -------------------------------------------------------------------------------- 1 | /** 2 | * 3 | */ 4 | 5 | export default class Index extends React.Component { 6 | 7 | constructor() { 8 | super(); 9 | } 10 | 11 | render() { 12 | return ( 13 |
14 | 15 |
16 | ); 17 | } 18 | 19 | componentDidMount () { 20 | 21 | } 22 | 23 | } 24 | 25 | -------------------------------------------------------------------------------- /profiles/dev/config.json: -------------------------------------------------------------------------------- 1 | { 2 | "env": "dev", 3 | 4 | "mysql": { 5 | "host" : "localhost", 6 | "user" : "root", 7 | "password" : "root", 8 | "database" : "testdb", 9 | "port" : 3306, 10 | "writeLog" : false 11 | }, 12 | 13 | "feUrl": "http://127.0.0.1:3000", 14 | "devServerUrl": "http://127.0.0.1:8888", 15 | 16 | "appRun": 8888 17 | } 18 | -------------------------------------------------------------------------------- /server/js/service/browserService.js: -------------------------------------------------------------------------------- 1 | /*@Service*/ 2 | module.exports = { 3 | /*@Autowired("browserDao")*/ 4 | browserDao: null, 5 | browserShare: function(param) { 6 | var pc = this.browserDao.browserShare(param, 'pc'), 7 | mobile = this.browserDao.browserShare(param, 'mobile'), 8 | list = [pc, mobile]; 9 | return Promise.all(list).then(function(data) { 10 | return data; 11 | }); 12 | } 13 | }; 14 | -------------------------------------------------------------------------------- /app.js: -------------------------------------------------------------------------------- 1 | var path = require('path'); 2 | var express = require('express'); 3 | var app = express(); 4 | 5 | // 静态资源目录; TODO: 静态资源推荐走 CDN 6 | app.use('/static', express.static(path.join(__dirname, 'static'))); 7 | 8 | // 首页 9 | app.get('/', require('server/js/controller/pageController').homepage); 10 | 11 | var server = app.listen(8888, function () { 12 | var port = server.address().port; 13 | console.log('Example app listening at http://127.0.0.1:' + port); 14 | }); 15 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | /dev/ 2 | /prd/ 3 | /refs/ 4 | 5 | 6 | # kdiff3 ignore 7 | *.orig 8 | 9 | # maven ignore 10 | target/ 11 | 12 | # eclipse ignore 13 | .settings/ 14 | .project 15 | .classpath 16 | 17 | # idea ignore 18 | .idea/ 19 | *.ipr 20 | *.iml 21 | *.iws 22 | 23 | # temp ignore 24 | *.log 25 | *.cache 26 | *.diff 27 | *.patch 28 | *.tmp 29 | 30 | # system ignore 31 | .DS_Store 32 | Thumbs.db 33 | 34 | # package ignore (optional) 35 | # *.jar 36 | # *.war 37 | # *.zip 38 | # *.tar 39 | # *.tar.gz 40 | 41 | 42 | .sass-cache 43 | /resource/ 44 | /log/ 45 | /node_modules/ -------------------------------------------------------------------------------- /static/js/common/ui/Header.js: -------------------------------------------------------------------------------- 1 | /** 2 | * 头部 3 | */ 4 | 5 | export default class Header extends React.Component { 6 | constructor() { 7 | super(); 8 | } 9 | 10 | render() { 11 | return ( 12 |
13 |
设置
14 |
退出
15 |
16 | ); 17 | } 18 | 19 | componentWillMount(){ 20 | 21 | } 22 | 23 | getDateDisplayStatus(){ 24 | 25 | } 26 | 27 | componentWillReceiveProps(){ 28 | 29 | } 30 | 31 | componentDidMount(){ 32 | 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2016 zincing 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /tools/makeFekitVerPlugin.js: -------------------------------------------------------------------------------- 1 | var fs = require('fs'), 2 | path = require('path'); 3 | 4 | var makeFekitVerPlugin = function(verPath, spliter) { 5 | this.verPath = verPath || __dirname; 6 | this.spliter = spliter || '@'; 7 | } 8 | 9 | makeFekitVerPlugin.prototype.apply = function(compiler) { 10 | var that = this; 11 | compiler.plugin("done", function(stats) { 12 | var json = stats.toJson(); 13 | var hash = json.hash, 14 | files = json.assets//json.assetsByChunkName; 15 | ensureDir([ 16 | path.join(that.verPath, 'ver'), 17 | path.join(that.verPath, 'ver/scripts'), 18 | path.join(that.verPath, 'ver/styles') 19 | ], fs.W_OK); 20 | var all = ""; 21 | files.forEach(function(file){ 22 | var fullname = file.name; 23 | var name = fullname.replace(that.spliter + hash, ''); 24 | fs.writeFileSync(path.join(that.verPath, 'ver/' + name + '.ver'), hash); 25 | all += fullname + '\n'; 26 | }); 27 | fs.writeFileSync(path.join(that.verPath, 'ver/versions.mapping'), all ); 28 | }); 29 | }; 30 | 31 | function ensureDir(paths, mode){ 32 | paths.forEach(function(path){ 33 | try { 34 | fs.accessSync(path, mode); 35 | } catch (e) { 36 | fs.mkdirSync(path); 37 | } 38 | }); 39 | } 40 | 41 | module.exports = makeFekitVerPlugin; -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "gulp-webpack-node", 3 | "version": "1.0.0", 4 | "description": "gulp-webpack-node project template.", 5 | "scripts": { 6 | "init": "npm install --registry https://registry.npm.taobao.org", 7 | "start": "node ./app.js" 8 | }, 9 | "repository": { 10 | "type": "git", 11 | "url": "https://github.com/functions/gulp-webpack-node.git" 12 | }, 13 | "jshintConfig": { 14 | "esnext": true 15 | }, 16 | "author": "", 17 | "license": "MIT", 18 | "dependencies": { 19 | "body-parser": "^1.13.3", 20 | "codemirror": "^5.16.0", 21 | "cookie-parser": "^1.3.5", 22 | "ejs": "^2.3.1", 23 | "express": "^4.13.4", 24 | "file-loader": "^0.8.5", 25 | "json-loader": "^0.5.4", 26 | "mysql": "^2.10.2", 27 | "promise": "^7.1.1", 28 | "react": "^15.2.1", 29 | "react-dom": "^15.2.1", 30 | "react-router": "^2.5.2", 31 | "serve-favicon": "^2.3.0", 32 | "url-loader": "^0.5.7" 33 | }, 34 | "devDependencies": { 35 | "babel-core": "^6.7.2", 36 | "babel-loader": "^6.2.4", 37 | "babel-preset-es2015": "^6.6.0", 38 | "babel-preset-react": "^6.5.0", 39 | "babel-preset-stage-0": "^6.5.0", 40 | "extract-text-webpack-plugin": "^1.0.1", 41 | "postcss-loader": "^0.9.1", 42 | "react-hot-loader": "^1.3.0", 43 | "sass-loader": "^3.2.0", 44 | "node-sass": "^3.8.0", 45 | "css-loader": "^0.23.1", 46 | "jsx-loader": "^0.13.2", 47 | "gulp": "^3.9.1", 48 | "gulp-clean": "^0.3.2", 49 | "gulp-copy": "0.0.2", 50 | "gulp-webpack": "^1.5.0", 51 | "style-loader": "^0.13.1", 52 | "webpack": "^1.12.14", 53 | "webpack-dev-server": "^1.14.1" 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /server/js/common/comRes.js: -------------------------------------------------------------------------------- 1 | 2 | module.exports = { 3 | success: function(res, data) { 4 | if (!res || 'function' !== typeof res.write) { 5 | console.warn("必须传入Response对象"); 6 | } 7 | var output = { 8 | status: 0, 9 | message: 'success', 10 | data : data 11 | }; 12 | res.setHeader('Content-Type', 'application/json'); 13 | res.write(JSON.stringify(output)); 14 | res.end(""); 15 | }, 16 | error: function(res, error) { 17 | if (!res || 'function' !== typeof res.write) { 18 | console.warn("必须传入Response对象"); 19 | } 20 | if(typeof error === 'string'){ 21 | error = { 22 | code : error 23 | }; 24 | } 25 | var output; 26 | if (error && this.ERRORSTATUS[error.code]) { 27 | output = this.ERRORSTATUS[error.code]; 28 | } else if (error && error.status) { 29 | output = error; 30 | } else { 31 | output = this.ERRORSTATUS.DEFAULT; 32 | } 33 | res.setHeader('Content-Type', 'application/json'); 34 | res.write(JSON.stringify(output)); 35 | res.end(""); 36 | }, 37 | // 消息码 38 | ERRORSTATUS: { 39 | DEFAULT : { 40 | status : -1, 41 | message : '服务器错误' 42 | }, 43 | NOLOGIN : { 44 | status : -101, 45 | message : '未登陆,请先登录' 46 | }, 47 | WAITTING:{ 48 | status : -404, 49 | message : '暂未开发,敬请等待' 50 | }, 51 | needParam:{ 52 | status : -1, 53 | message : '缺少参数' 54 | } 55 | } 56 | }; 57 | -------------------------------------------------------------------------------- /server/js/dao/db.js: -------------------------------------------------------------------------------- 1 | var mysql = require("mysql"); 2 | 3 | // 连接池容量 4 | var POOL_SIZE = 10, 5 | cwd = process.cwd(), 6 | config = require(cwd + "/resource/config.js"), 7 | CONNECT_CONFIG = { 8 | "info": config 9 | }; 10 | 11 | //数据库链接方法 12 | var connect = { 13 | mysql: function(pattern, sql, data, callback) { 14 | if (!pattern.pool) { 15 | pattern.info.connectionLimit = POOL_SIZE; 16 | pattern.pool = mysql.createPool(pattern.info); 17 | } 18 | 19 | pattern.pool.getConnection(function(error, connection) { 20 | // 输出sql和data 21 | console.info("excute sql:", sql); 22 | console.info("by data:", data); 23 | if (error) { 24 | console.error('获取数据库连接异常!\n', error); 25 | callback({ 26 | error: error 27 | }); 28 | return; 29 | } 30 | 31 | connection.query(sql, data, function(err, results) { 32 | // 返回连接池 33 | connection.release(function(error) { 34 | if (error) { 35 | console.error('关闭数据库连接异常!\n', error); 36 | } 37 | }); 38 | 39 | if (err) { 40 | err.sql = sql; 41 | console.error("db error:", err); 42 | callback({ 43 | error: err 44 | }); 45 | return; 46 | } 47 | callback(results); 48 | }); 49 | }); 50 | } 51 | }; 52 | 53 | exports.execSQL = function(sql, data) { 54 | return new Promise(function(resolve, reject){ 55 | connect.mysql(CONNECT_CONFIG, sql, data, function(result){ 56 | if (result.error) { 57 | reject(result); 58 | return; 59 | }else { 60 | resolve(result); 61 | return; 62 | } 63 | }); 64 | }); 65 | }; 66 | -------------------------------------------------------------------------------- /gulpfile.js: -------------------------------------------------------------------------------- 1 | var Path = require('path'); 2 | var gulp = require('gulp'); 3 | var clean = require('gulp-clean'); 4 | var config = require('./resource/config.json'); 5 | 6 | /************************** 7 | * webpack * 8 | **************************/ 9 | gulp.task('webpack', function() { 10 | var webpackConfig = require('./webpack.config'); 11 | var gulpWebpack = require('gulp-webpack'); 12 | var dir = Path.join('static', 'build'); 13 | 14 | return gulp.src(dir) 15 | .pipe(clean()) 16 | .pipe(gulpWebpack(webpackConfig)) 17 | .pipe(gulp.dest(dir)); 18 | }); 19 | /************************** 20 | * webpack-dev-server * 21 | **************************/ 22 | gulp.task('webpack-dev-server', function() { 23 | //start webpack develop server 24 | var webpackConfig = require('./webpack.dev.config'); 25 | var WebpackDevServer = require('webpack-dev-server'); 26 | var webpack = require('webpack'); 27 | 28 | new WebpackDevServer(webpack(webpackConfig), { 29 | contentBase: config.devServerUrl, 30 | publicPath: webpackConfig.output.publicPath, 31 | hot: true, 32 | noInfo: false, 33 | historyApiFallback: true, 34 | proxy: { '*': config.devServerUrl } 35 | }).listen(3000, 'localhost', function(err) { 36 | if (err) console.log(err); 37 | console.log('Listening at localhost:3000'); 38 | open('http://127.0.0.1:3000/webpack-dev-server/'); 39 | }); 40 | }); 41 | /************************** 42 | * copy profiles * 43 | **************************/ 44 | gulp.task('copyProfile', function() { 45 | var allowEnv = ['dev', 'beta', 'prod']; 46 | var env = process.argv[2] || allowEnv[0]; 47 | if (allowEnv.indexOf(env) === -1) { 48 | env = allowEnv[0]; 49 | } 50 | return gulp.src(Path.join(__dirname, 'profiles', env, '*')) 51 | .pipe(gulp.dest(Path.join(__dirname, 'resource'))); 52 | }); 53 | /************************** 54 | * Main * 55 | **************************/ 56 | gulp.task('dev', ['copyProfile', 'webpack-dev-server']); 57 | gulp.task('beta', ['webpack']); 58 | gulp.task('prod', ['webpack']); 59 | -------------------------------------------------------------------------------- /webpack.libs.js: -------------------------------------------------------------------------------- 1 | /** 2 | * configuration description 3 | * https://github.com/webpack/docs/wiki/configuration#configuration-object-content 4 | * webpack document 5 | * http://webpack.github.io/docs/ 6 | */ 7 | 'use strict' 8 | var webpack = require('webpack'); 9 | var Path = require('path'); 10 | 11 | //提取css独立成文件 12 | var ExtractTextPlugin = require('extract-text-webpack-plugin'); 13 | var extractSCSS = new ExtractTextPlugin('[name].min.css'); 14 | var ProgressPlugin = require('webpack/lib/ProgressPlugin'); 15 | var libsPath = Path.join(__dirname, 'static', 'libs'); 16 | 17 | module.exports = { 18 | //生成sourcemap,便于开发调试 19 | devtool: "source-map", 20 | //获取项目入口js文件 21 | entry: { 22 | 'react': libsPath + '/react.js', 23 | 'react-dom': libsPath + '/react-dom.js', 24 | 'react-router': libsPath + '/react-router.js', 25 | 'antd': libsPath + '/antd.js' 26 | }, 27 | output: { 28 | //文件输出目录 29 | path: Path.join(__dirname, 'static', 'libs'), 30 | //根据入口文件输出的对应多个文件名 31 | filename: '[name].min.js' 32 | }, 33 | resolve: { 34 | extensions: ['', '.js', '.scss', '.json', '.jsx', '.css'] 35 | }, 36 | //各种加载器,即让各种文件格式可用require引用 37 | module: { 38 | loaders: [ 39 | //.js 或 .jsx 文件使用 babel-loader 来编译处理 40 | { 41 | test: /\.jsx?$/, 42 | loaders: ['react-hot', 'babel-loader?presets[]=react,presets[]=es2015,presets[]=stage-0'], 43 | include: [Path.join(__dirname, 'static', 'libs')] 44 | }, 45 | //.css 文件使用 style-loader、 css-loader 和 autoprefixer-loader 来处理 46 | // style-loader:将css插入到页面的style标签,由于使用该loader会报错,故不用 47 | // css-loader:处理css文件中的url()等 48 | { 49 | test: /\.css$/, 50 | loader: 'css!autoprefixer' 51 | }, 52 | //图片文件使用 url-loader 来处理,小于8kb的直接转为base64 53 | { 54 | test: /\.(png|jpg)$/, 55 | loader: 'url-loader?limit=8192' 56 | }, 57 | //.scss 文件使用 style-loader、css-loader、autoprefixer 和 sass-loader 来编译处理 58 | { 59 | test: /\.scss$/, 60 | exclude: /node_modules/, 61 | loader: extractSCSS.extract('css!autoprefixer!sass?sourceMap') 62 | } 63 | ] 64 | }, 65 | plugins: [ 66 | new ProgressPlugin(function(percentage, msg) { 67 | console.log(parseInt(percentage * 100) + '%', msg); 68 | }), 69 | extractSCSS, 70 | //js文件的压缩 71 | new webpack.optimize.UglifyJsPlugin({ 72 | compress: { 73 | warnings: false 74 | } 75 | }) 76 | ] 77 | }; 78 | -------------------------------------------------------------------------------- /webpack.dev.config.js: -------------------------------------------------------------------------------- 1 | /** 2 | * configuration description 3 | * https://github.com/webpack/docs/wiki/configuration#configuration-object-content 4 | * webpack document 5 | * http://webpack.github.io/docs/ 6 | */ 7 | 'use strict' 8 | var webpack = require('webpack'); 9 | var ProgressPlugin = require('webpack/lib/ProgressPlugin'); 10 | var Path = require('path'); 11 | 12 | var webpackHMR = [ 13 | 'webpack-dev-server/client?http://127.0.0.1:3000', 14 | 'webpack/hot/dev-server' 15 | ]; 16 | 17 | module.exports = { 18 | //生成sourcemap,便于开发调试 19 | devtool: "source-map", 20 | //获取项目入口js文件 21 | entry: { 22 | //添加入口,以及HMR inline 23 | app: webpackHMR.concat('./static/js/app.js') 24 | }, 25 | output: { 26 | //文件输出目录 27 | path: Path.join(__dirname, 'prd'), 28 | //用于配置文件发布路径,如CDN或本地服务器 29 | publicPath: '/prd/', 30 | //根据入口文件输出的对应多个文件名 31 | filename: '[name].js' 32 | }, 33 | resolve: { 34 | alias: { 35 | 'style': Path.join(__dirname, 'static', 'style') 36 | }, 37 | extensions: ['', '.js', '.scss', '.json', '.jsx', '.css'] 38 | }, 39 | //各种加载器,即让各种文件格式可用require引用 40 | module: { 41 | loaders: [ 42 | //.js 或 .jsx 文件使用 babel-loader 来编译处理 43 | { 44 | test: /\.jsx?$/, 45 | loaders: ['react-hot', 'babel-loader?presets[]=react,presets[]=es2015,presets[]=stage-0'], 46 | include: [Path.join(__dirname, 'static', 'js')] 47 | }, 48 | //.css 文件使用 style-loader、 css-loader 和 autoprefixer-loader 来处理 49 | // style-loader:将css插入到页面的style标签,由于使用该loader会报错,故不用 50 | // css-loader:处理css文件中的url()等 51 | { 52 | test: /\.css$/, 53 | loader: 'style!css!autoprefixer' 54 | }, 55 | { 56 | test: /.(png|woff(2)?|eot|ttf|svg)(\?[a-z0-9=\.]+)?$/, 57 | loader: 'url-loader?limit=100000' 58 | }, 59 | //.scss 文件使用 style-loader、css-loader、autoprefixer 和 sass-loader 来编译处理 60 | { 61 | test: /\.scss$/, 62 | exclude: /node_modules/, 63 | loaders: ["style", "css?sourceMap", "autoprefixer", "sass?sourceMap"] 64 | }, 65 | //.json 文件使用json-loader 来编译处理 66 | { 67 | test: /\.json$/, 68 | loader: 'json-loader' 69 | } 70 | ] 71 | }, 72 | plugins: [ 73 | new ProgressPlugin(function(percentage, msg) { 74 | console.log(parseInt(percentage * 100) + '%', msg); 75 | }), 76 | //提取公共脚本,默认只有一个入口时可以不用,否则需要额外引入common.js 77 | new webpack.optimize.CommonsChunkPlugin('common.js'), 78 | //增加公共头部 79 | new webpack.BannerPlugin(), 80 | //增加HMR(模块热插拔) 81 | new webpack.HotModuleReplacementPlugin(), 82 | new webpack.NoErrorsPlugin() 83 | ] 84 | }; 85 | -------------------------------------------------------------------------------- /webpack.config.js: -------------------------------------------------------------------------------- 1 | /** 2 | * configuration description 3 | * https://github.com/webpack/docs/wiki/configuration#configuration-object-content 4 | * webpack document 5 | * http://webpack.github.io/docs/ 6 | */ 7 | 'use strict' 8 | var webpack = require('webpack'); 9 | var Path = require('path'); 10 | 11 | //提取css独立成文件 12 | var ExtractTextPlugin = require("extract-text-webpack-plugin"); 13 | var ProgressPlugin = require('webpack/lib/ProgressPlugin'); 14 | var extractSCSS = new ExtractTextPlugin('[name].css'); 15 | // var extractSCSS = new ExtractTextPlugin('[name]-[hash].css'); 16 | var makeFekitVerPlugin = require("./makeFekitVerPlugin"); 17 | 18 | module.exports = { 19 | //生成sourcemap,便于开发调试 20 | devtool: "source-map", 21 | //获取项目入口js文件 22 | entry: { 23 | index: './static/js/app.js' 24 | }, 25 | output: { 26 | //文件输出目录 27 | path: Path.join(__dirname, 'build'), 28 | //用于配置文件发布路径,如CDN或本地服务器 29 | publicPath: '/build/', 30 | //根据入口文件输出的对应多个文件名 31 | filename: '[name].js' 32 | // filename: '[name]@[hash].js' 33 | }, 34 | resolve: { 35 | alias: { 36 | 'Styles': Path.join(__dirname, 'static', 'style') 37 | }, 38 | extensions: ['', '.js', '.scss', '.json', '.jsx', '.css'] 39 | }, 40 | //各种加载器,即让各种文件格式可用require引用 41 | module: { 42 | // preLoaders: [{ 43 | // test: /\.jsx?$/, 44 | // exclude: /node_modules/, 45 | // loader: 'jsxhint' 46 | // }], 47 | loaders: [ 48 | //.js 或 .jsx 文件使用 babel-loader 来编译处理 49 | { 50 | test: /\.jsx?$/, 51 | loaders: ['react-hot', 'babel-loader?presets[]=react,presets[]=es2015,presets[]=stage-0'], 52 | include: [Path.join(__dirname, 'static', 'js')] 53 | }, 54 | //.css 文件使用 style-loader、 css-loader 和 autoprefixer-loader 来处理 55 | // style-loader:将css插入到页面的style标签,由于使用该loader会报错,故不用 56 | // css-loader:处理css文件中的url()等 57 | { 58 | test: /\.css$/, 59 | loader: 'css!autoprefixer' 60 | }, 61 | //图片文件使用 url-loader 来处理,小于8kb的直接转为base64 62 | { 63 | test: /\.(png|jpg)$/, 64 | loader: 'url-loader?limit=8192' 65 | }, 66 | //.scss 文件使用 style-loader、css-loader、autoprefixer 和 sass-loader 来编译处理 67 | { 68 | test: /\.scss$/, 69 | exclude: /node_modules/, 70 | loader: extractSCSS.extract('css!autoprefixer!sass?sourceMap') 71 | }, 72 | //.json 文件使用json-loader 来编译处理 73 | { 74 | test: /\.json$/, 75 | loader: 'json-loader' 76 | } 77 | ] 78 | }, 79 | plugins: [ 80 | new ProgressPlugin(function(percentage, msg) { 81 | console.log(parseInt(percentage * 100) + '%', msg); 82 | }), 83 | //提取公共脚本,默认只有一个入口时可以不用,否则需要额外引入common.js 84 | new webpack.optimize.CommonsChunkPlugin('common.js'), 85 | // new webpack.optimize.CommonsChunkPlugin('common@[hash].js'), 86 | extractSCSS, 87 | //增加公共头部 88 | new webpack.BannerPlugin('Author by robin!'), 89 | //增加HMR(模块热插拔) 90 | new webpack.HotModuleReplacementPlugin(), 91 | new webpack.NoErrorsPlugin(), 92 | //js文件的压缩 93 | new webpack.optimize.UglifyJsPlugin({ 94 | compress: { 95 | warnings: false 96 | } 97 | }), 98 | //生成和fekit一致的ver文件 99 | new makeFekitVerPlugin() 100 | ] 101 | }; 102 | --------------------------------------------------------------------------------