本文作为搭建个人博客的开端,将会配置环境,以后做别的project也可以以此开始。代码托管在github。
code: https://github.com/MSChuan/Blog-UI,
demo: https://mschuan.github.io/Blog-UI/dist_prod/index.html
和todolist类似,使用框架webpack+react+redux,由于要实现UI,选择使用react-bootstrap,响应式布局,方便实用,前端路由则用react-router,算是react的经典搭配。
npm init
npm install react react-dom redux react-redux redux-thunk css-loader style-loader sass-loader node-sass file-loader url-loader autoprefixer postcss-loader --save
npm install webpack -g
npm install webpack --save-dev
npm install extract-text-webpack-plugin html-webpack-plugin --save-dev
npm install babel-loader babel-core babel-preset-es2015 babel-preset-react babel-preset-stage-2 babel-plugin-transform-decorators-legacy babel-plugin-import babel-cli --save-dev
npm install path webpack-dev-server redux-devtools redux-devtools-log-monitor redux-devtools-dock-monitor react-hot-loader@next --save-dev
npm install bootstrap react-bootstrap react-router react-router-dom --save
分析一下webpack的配置,为了分开开发和发布环境的配置,这里使用了两个配置文件,分别是webpack.config.js和webpack.config.prod.js,在package.json中封装一下运行的命令。
"scripts": {
"start": "node server",
"build": "webpack --config ./webpack.config.prod.js --progress --profile --colors"
}
这样运行npm start即可启动本地测试服务器,运行npm run build即可使用webpack.config.prod.js打包production版本的代码,运行webpack即可打包成debug版本。
在config的开头设置entry,指定打包的入口文件以及一些热加载需要用到的路径,vendor是单独打包指定的依赖。
entry: {
index: [
'webpack-dev-server/client?http://localhost:3000',
'webpack/hot/only-dev-server',
'react-hot-loader/patch',
path.join(__dirname, 'src/index.js')
],
vendor: [ // pack react and react-dom independently
"react",
"react-dom",
"react-bootstrap"
]
},
之后是输出文件路径:
output: {
path: path.join(__dirname, 'dist/'),
filename: "js/[name].js",
publicPath: './'
},
path是打包文件的输出路径,__dirname是当前配置文件的路径,所以这里指定了在dist目录下输出打包文件,filename是打包的入口js文件路径,它是相对于path的相对路径,这样设置的输出为__dirname/dist/js/index.js,publicPath非常重要,它与path没什么关系,如果是相对路径,就是相对于index.html所在目录,也可以直接是静态资源缓存url,比如cdn的url。它的作用是指定代码中引用的根目录,比如css中image的url。后文会讲到我们需要设置背景图片的颜色,css代码中是这样的:
background: url('../resource/image/topimage.jpg') no-repeat;
publicPath设置为’./’,所以打包后的代码中:
background: url(./resource/image/topimage.jpg) no-repeat;
这里出现比较神奇的一幕,打包前的’../’被忽略了,相当于publicPath + ‘resource/image/topimage.jpg’,所以打包后的css文件需要和index.html在同一目录下才能有效。
loaders里就是加载对应资源文件的配置。
module: {
loaders: [{ // babel loader
test: /\.js?$/,
exclude: /node_modules/,
loader: "babel-loader"
}, {
test: /\.(scss|sass|css)$/, // pack sass and css files
loader: ExtractTextPlugin.extract({fallback: "style-loader", use: "css-loader!sass-loader"})
}, {
test: /\.(png|jpg|jpng)$/, // pack images
loader: 'url-loader?limit=8192&name=resource/image/[name].[ext]'
},
{
test: /\.(woff|woff2|eot|ttf|svg)(\?[a-z0-9]+)?$/,
loader: 'url-loader?limit=1000&name=resource/fonts/[name].[ext]'
}
]
},
对于开发环境,使用如下plugins:
plugins: [
new HtmlWebpackPlugin({
template: 'src/index.tpl.html',
inject: 'body',
filename: 'index.html'
}),
new webpack.optimize.CommonsChunkPlugin("bundle/vendor.bundle.js"), //packed independently such as react and react-dom
new ExtractTextPlugin("index.css"), // pack all the sass and css files into index.csss
new webpack.HotModuleReplacementPlugin(),
new webpack.NoEmitOnErrorsPlugin(),
new webpack.DefinePlugin({
'process.env.NODE_ENV': JSON.stringify('development')
})
]
对于发布版本的打包则有些不同:
plugins: [
new HtmlWebpackPlugin({
template: 'src/index.tpl.html',
inject: 'body',
filename: 'index.html'
}),
new webpack.optimize.CommonsChunkPlugin("bundle/vendor.bundle.js"), //packed independently such as react and react-dom
new ExtractTextPlugin("[name]-[hash].min.css"), // pack all the sass and css files into css file
new webpack.optimize.UglifyJsPlugin({ // handles uglifying js
compressor: {
warnings: false,
screw_ie8: true
}
}),
new webpack.DefinePlugin({
'process.env.NODE_ENV': JSON.stringify('production')
}),
new webpack.LoaderOptionsPlugin({
options: {
postcss: function () {
return [require('autoprefixer')];
}
}
})
]
增加了代码优化,css自动加前缀实现跨浏览器呈现。UI的搭建将在下一篇文章中介绍。