搭建一个 gulp + webpack 的环境去学 react ,环境没有区分生产和开发环境,后续会完善,新手可以看一下。
项目目录:
config
- webpack.configjs // webpack 配置信息
- configuration.init.js // 配置变量,例如输出目录等
public // 打包后的输出目录
src // 开发目录
- js
- css
- static
- views
- app.js
index.html
gulpfile.js
.babelrc
.babelrc // env 编译 es6,es7,react 等
{
"presets": [
[
"env",
{
"targets": {
"node": "current",
"browsers": ["last 2 versions", "ie >= 7"]
}
}
]
]
}
configuration.init.js // 这里放一些配置的全局变量,后续可以把更多的配置加入
module.exports = {
outPath: 'public' // 打包后输出到 public 目录
}
webpack.config.js
const path = require('path')
const webpack = require('webpack')
const ExtractTextPlugin = require('extract-text-webpack-plugin')
const HtmlWebpackPlugin = require('html-webpack-plugin')
const configuration = require('./configuration.init.js')
const _path = path.resolve(__dirname, '../')
module.exports = {
// 这里配置不同环境或不同需求的 webpack 配置,导出后在 gulp 引入
dev: {
entry: {
app: path.resolve(_path, 'src/app.js'),
},
output: {
path: `${path.resolve(_path)}/${configuration.outPath}`,
filename: 'js/[name].[hash].js'
},
module: {
loaders: [
{
test: /\.js$/,
exclude: /node_modules/,
loader: 'babel-loader',
query: {
presets: ['env', 'react', 'stage-0']
}
},
{
test: /\.scss$/,
loader: ExtractTextPlugin.extract('css-loader?minimize!sass-loader')
},
{
test: /\.css$/,
loader: ExtractTextPlugin.extract('style-loader!css-loader?minimize'),
},
{
test: /\.(jpg|png)$/,
loaders: ['url-loader']
},
{
test: /\.json$/,
loaders: ['json-loader'],
}
],
},
plugins: [
new webpack.optimize.CommonsChunkPlugin({
name: 'common',
filename: 'js/[name].[hash].js',
minChunks: 3, // 有三个文件都用到才打包
}),
new webpack.optimize.UglifyJsPlugin({
compress: {
warnings: false,
},
}),
new ExtractTextPlugin(`css/[name].[hash].css`),
new HtmlWebpackPlugin({
// 打包 html 文件,并自动把打包后的加入 hash 值的 js,css 文件引入
template: `${_path}/index.html`,
filename: `${_path}/${configuration.outPath}/index.html`,
// hash: true // js等文件后加 ?[hash]
}),
],
resolve: {
extensions: ['.js', '.json', '.scss', '.png', 'jpg'],
}
}
}
gulpfile.js
const fs = require('fs')
const path = require('path')
const gulp = require('gulp')
const webpack = require('webpack')
const merge = require('merge-stream')
const runSequence = require('run-sequence') // 同步执行任务
const del = require('del')
const gulpLoadPlugins = require('gulp-load-plugins')
const browserSync = require('browser-sync')
const ExtractTextPlugin = require('extract-text-webpack-plugin')
const HtmlWebpackPlugin = require('html-webpack-plugin')
// 配置
const configuration = require('./config/configuration.init.js')
const webpackConfig = require('./config/webpack.config.js')
// 变量
const gulps = gulpLoadPlugins()
const version = parseInt(Math.random() * 10000000, 10) + 10000000
const con = {
getType(val) {
// 获取数据类型
return Object.prototype.toString.apply(val).toLowerCase()
},
// 时间如果个位数加 0
timeFormat(time) {
time = this.getType(time) === '[object string]' ? time : String(time)
return time.length === 1 ? '0' + time : time
},
// 得到 [12:23:01] 格式的时间
getTime() {
const nowTime = new Date()
return `${this.timeFormat(nowTime.getHours())}:${this.timeFormat(nowTime.getMinutes())}:${this.timeFormat(nowTime.getSeconds())}`
},
// 终端彩色打印,col(1-6) 参数是颜色
// 无限链式调用,最后一个括号不能省略 con.log('aaa', 1)('bbb', 6)('ccc', 2)()
// 最后的括号里如果加入 false 参数则不打印时间
// 输出 => [00:00:00] aaabbbccc // 输出一串不同颜色的字符串
log(text, col = 6) {
let args = []
args.push(`\x1b[3${col}m${text}\x1b[0m`)
const fn_curry = (text_c, col_c = 6) => {
if(text_c === void 0 || this.getType(text_c) === '[object boolean]') {
text_c === void 0 || text_c === true ? args.unshift(`[\x1b[34m${this.getTime()}\x1b[0m] `) : null
return console.log(args.join(''))
} else {
args.push(`\x1b[3${col_c}m${text_c}\x1b[0m`)
return fn_curry }
}
return fn_curry
},
}
// 清理文件
gulp.task('clean', () => del([`${configuration.outPath}/**/*`]));
// 复制文件
gulp.task('copy', () => {
merge(
// 图片
gulp.src('./src/img/**/*')
.pipe(gulps.changed(`./${configuration.outPath}/img`))
.pipe(gulp.dest(`./${configuration.outPath}/img`)),
// 复制图标
gulp.src('./favicon.ico')
.pipe(gulps.changed(`./${configuration.outPath}`))
.pipe(gulp.dest(`./${configuration.outPath}`)) )
})
// webpack
gulp.task('webpack-dev', ['copy'], (callback) => {
webpack(
webpackConfig.dev, // webpack 打包配置导入
(err, stats) => {
if (err) {
console.log(err, 'err') } // 错误处理
if (stats.compilation.errors.length > 0) {
console.log(stats.compilation.errors[0].message, 'message')
}
// webpack 的打包信息另存为 txt 文件
fs.writeFile(`${__dirname}/${configuration.outPath}/webpack.result.${stats.hash}.txt`, stats, (err) =>{
if(err){
console.log(err);
}else{
con.log(`webpack unpack info path: ${__dirname}/${configuration.outPath}/webpack.result.${stats.hash}.txt`, 5)()
}
})
// webpack 输出日志
con.log('******************\n\n', 2)()
con.log(`${String(stats)}\n\n`, 4)()
con.log('hash: ', 4)(stats.hash)()
con.log('time: ', 4)(`${(stats.endTime - stats.startTime) / 1000}s`)()
console.log('\n\n')
con.log('******************', 2)()
console.log('webpack-dev', 'done')
callback()
})
})
gulp.task('watch', function () {
gulp.watch([
`${__dirname}/src/**/*`,
], [
'clean',
'webpack-dev'
])
})
// 浏览器自动刷新
gulp.task('sync', () => {
browserSync.init({
proxy: 'localhost:10086',
host: 'index.aaa.com',
port: '10087',
open: 'external',
});
gulp.watch(`${configuration.outPath}/**/*.*`).on('change', browserSync.create().reload);
})
// 默认任务
gulp.task('default', (cb) => {
runSequence('clean', [
'copy',
'webpack-dev',
], cb)
});
// dev任务
gulp.task('dev', (cb) => {
runSequence('clean', 'watch', [
// 'sync',
'copy',
'webpack-dev',
], cb)
})
// build
gulp.task('build', (cb) => {
runSequence('clean', [
'copy',
'webpack-dev',
], cb)
})
package.json
{
"name": "react_test",
"version": "1.0.0",
"description": "this is a project for react practice",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
"dev": "NODE_ENV=development gulp dev",
"build": "npm run clean && NODE_ENV=production gulp build",
"clean": "rm -rf public"
},
"author": "wenjiawei",
"license": "ISC",
"dependencies": {
"babel-core": "^6.26.0",
"babel-loader": "^7.1.2",
"babel-polyfill": "^6.26.0",
"babel-preset-env": "^1.6.1",
"babel-preset-react": "^6.24.1",
"babel-preset-stage-0": "^6.24.1",
"browser-sync": "^2.23.6",
"css-loader": "^0.28.9",
"del": "^3.0.0",
"extract-text-webpack-plugin": "^3.0.2",
"gulp": "^3.9.1",
"gulp-changed": "^3.2.0",
"gulp-html-replace": "^1.6.2",
"gulp-load-plugins": "^1.5.0",
"html-webpack-plugin": "^2.30.1",
"lodash": "^4.17.4",
"merge-stream": "^1.0.1",
"node-sass": "^4.7.2",
"react": "^16.2.0",
"react-dedux": "^0.4.0-beta.4",
"react-dom": "^16.2.0",
"react-redux": "^5.0.6",
"react-router": "^4.2.0",
"redux": "^3.7.2",
"run-sequence": "^2.2.1",
"sass": "^1.0.0-beta.4",
"sass-loader": "^6.0.6",
"style-loader": "^0.20.1",
"webpack": "^3.10.0"
}
}
原文链接:http://blog.csdn.net/qq_25243451/article/details/79248499