前端工具的演化,可以说应接不暇。我在具体业务实践中,尝试和接触过grunt,fis,glup等脚手架的流程。在应用这些工具的过程中,对开发流程模棱两可,虽说是简单的打包,转译,压缩,混淆等等,但具体实现起来,怎么优化等等甚至路径的配置等等,都需要实践才能领会。学习操作系统最好的方式就是做系统,那么学习脚手架的流程,最好的方式也应该如此。首先需要梳理一下前端开发常见的工作流:
一般的前端在开发过程中常用的资源只有HTML,CSS,JS和一些图片资源,可能会存在少量的音频甚至视频资源。对于这些,我们早已不是直接在编写HTML和CSS文件了。HTML可以用插件生成,CSS可能会遇到预编译工具,常见如LESS,SASS,JS使用方式更多样,有适用于大型系统的超集JS:TypeScript,也有可以转义ES6的Babel,如果使用了某种MVVM模式的框架,如react,vue,其中丰富的JSX语法和组建的概念,使得前端的开发流程大放异彩的同时,也提升了可维护性。在webpack作为前端脚手架的灵魂般存在的同时,我们在不同的阶段:开发,部署,上线都有着不同的需求,这其中必然要使用不一样的插件,脚本去实现目的。
这是packjson.json的配置
{
"name": "toddmark",
"version": "1.0.0",
"description": "build a custiom blod ",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
"build": "rm -rf build && webpack",
"release": "git add . && git commit -m \"/****** release ******/\" && git push ",
"dev": "cross-env NODE_ENV=development node dev-server.js"
},
"repository": {
"type": "git",
"url": "git+https://github.com/toddmark/toddmark.git"
},
"author": "Todd Mark",
"license": "ISC",
"bugs": {
"url": "https://github.com/toddmark/toddmark/issues"
},
"homepage": "https://github.com/toddmark/toddmark#readme",
"devDependencies": {
"babel-core": "^6.21.0",
"babel-loader": "^6.2.10",
"babel-preset-es2015": "^6.18.0",
"babel-preset-react": "^6.16.0",
"cross-env": "^3.1.3",
"css-loader": "^0.26.1",
"extract-text-webpack-plugin": "^1.0.1",
"file-loader": "^0.9.0",
"html-loader": "^0.4.4",
"html-webpack-plugin": "^2.24.1",
"imports-loader": "^0.7.0",
"less": "^2.7.1",
"less-loader": "^2.2.3",
"react-hot-loader": "^1.3.1",
"style-loader": "^0.13.1",
"webpack": "^1.14.0",
"webpack-dev-server": "^1.16.2"
},
"dependencies": {
"bootstrap": "^3.3.7",
"d3": "^4.4.1",
"jquery": "^3.1.1",
"react": "^15.4.1",
"react-d3-library": "^1.1.7",
"react-dom": "^15.4.1",
"react-router": "^3.0.0"
}
}
这是一段webpack.config.js的配置。
const path = require('path');
const webpack = require('webpack');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const ExtractTextPlugin = require("extract-text-webpack-plugin");
let isDev = false;
const env = process.env.NODE_ENV;
isDev = env === 'development' ? true : false;
console.log(isDev ? '开发环境' : '生产环境');
module.exports = {
entry: {
vendor: ['jquery', 'bootstrap'],
index: ['./index.js']
},
devtool: 'source-map',
output: {
path: path.resolve('build'),
publicPath: isDev ? '/' : `./`,
filename: '[name]-[hash].js'
},
// externals: {
// react: 'React',
// 'react-dom':'ReactDOM',
// },
module: {
loaders: [{
test: /\.html$/,
loader: 'html'
}, {
test: /\.less$/,
loader: "style-loader!css-loader!less-loader"
}, {
test: /\.css$/,
loader: "style-loader!css-loader"
}, {
test: /\.(eot|woff|ttf|eot|woff2)$/, loader: "file-loader"
}, {
test: /\.jsx?$/,
exclude: /node_modules/,
loaders: ['react-hot', 'babel-loader?presets[]=es2015,presets[]=react']
}, {
test: /.*\.(gif|png|jpe?g|svg)$/i,
loader: "file-loader?name=img-[sha512:hash:base64:7].[ext]"
},{
test: /bootstrap.+\.(jsx|js)$/, loader: 'imports?jQuery=jquery,$=jquery,this=>window'
}
]
},
plugins:[
new webpack.optimize.CommonsChunkPlugin(/* chunkName= */"vendor", /* filename= */"vendor.bundle.js"),
new HtmlWebpackPlugin({
template: 'template/index.html'
})
].concat(
isDev ?
new webpack.HotModuleReplacementPlugin() :
[
new webpack.optimize.UglifyJsPlugin({
compress: {
warnings: false
}
}),
new webpack.DefinePlugin({
'process.env': {
NODE_ENV: JSON.stringify('production')
}
})
]
)
}
package.json没啥好说的,纯粹的包管理目录文件,详细的文档可以在这里看到。我们在这里配置的一些简单的脚本,如下:
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
"build": "rm -rf build && webpack",
"release": "git add . && git commit -m \"/****** release ******/\" && git push ",
"dev": "cross-env NODE_ENV=development node dev-server.js"
},
【build】顾名思义是用来编译用于发布的文件。【release】当然就是提交编译记录并且自动发布的意思。这其中有个【dev】是用来开发时使用,有一段不常见的标记cross-env
,这个是为了兼容window下的NODE_ENV配置才引入的。我们可以看到,当使用开发脚本时,CLI会两件事:1,设置node环境。2,在node环境中使用dev-server.js脚本。如下:
const webpack = require('webpack');
const config = require('./webpack.config.js');
const port = 8000;
config.entry.index.unshift(`webpack-dev-server/client?http://localhost:${port}/`, 'webpack/hot/dev-server');
const WebpackDevServer = require('webpack-dev-server');
const compiler = webpack(config);
const server = new WebpackDevServer(compiler, {
hot: true,
stats: {
colors: true,
chunks: false
}
})
server.listen(port);
console.log(`Listenting at http://localhost:${port}`);
可以看到,这段脚本里,我们使用了webpack.config.js的一些配置内容。然后开启了热价在模式,当执行完毕,我们的开发服务器也就启动成功了。可以看到这里我们使用了自动刷新的脚本()The webpack-dev-server supports multiple modes to automatically refresh the page),并且开启了热替换模式。