webpack打包发布
粗略的说明了一下打包的文件和大概的流程.
执行npm run build开始打包
调用build.js
然后主要调用webpack.prod.conf(有其他依赖,例如webpack.base.conf)
关于发布,就大概说了一下如何对已经进行发布的js,css,html进行一个小型服务器的发布
执行node prod.server.js 启动服务器
npm run build
执行该命令会build出相关文件,就是所谓的打包
> node build/build.js
⠇ building for production...(node:39190) DeprecationWarning: loaderUtils.parseQuery() received a non-string value which can be problematic, see https://github.com/webpack/loader-utils/issues/56
parseQuery() will be replaced with getOptions() in the next major version of loader-utils.
⠏ building for production...
Starting to optimize CSS...
Processing static/css/app.96a4b597fd49bcceebc8ed9975532dad.css...
Processed static/css/app.96a4b597fd49bcceebc8ed9975532dad.css, before: 227144, after: 227076, ratio: 99.97%
Hash: d8fa2ea68ff7eeb5bdb1
Version: webpack 2.2.1
Time: 10500ms
Asset Size Chunks Chunk Names
static/js/app.5136d78e51734a561a01.js 29.7 kB 0, 2 [emitted] app
static/js/vendor.0565b24a91810aaf3061.js 142 kB 1, 2 [emitted] vendor
static/js/manifest.c8353bb1e98b372587d9.js 1.5 kB 2 [emitted] manifest
static/css/app.96a4b597fd49bcceebc8ed9975532dad.css 227 kB 0, 2 [emitted] app
static/js/app.5136d78e51734a561a01.js.map 212 kB 0, 2 [emitted] app
static/css/app.96a4b597fd49bcceebc8ed9975532dad.css.map 55.3 kB 0, 2 [emitted] app
static/js/vendor.0565b24a91810aaf3061.js.map 1.03 MB 1, 2 [emitted] vendor
static/js/manifest.c8353bb1e98b372587d9.js.map 14.1 kB 2 [emitted] manifest
index.html 616 bytes [emitted]
static/css/reset.css 1.1 kB [emitted]
Build complete.
会执行build,会产生dist目录
dist
|-- index.html
`-- static
|-- css
| |-- app.96a4b597fd49bcceebc8ed9975532dad.css
| |-- app.96a4b597fd49bcceebc8ed9975532dad.css.map
| `-- reset.css
`-- js
|-- app.5136d78e51734a561a01.js
|-- app.5136d78e51734a561a01.js.map
|-- manifest.c8353bb1e98b372587d9.js
|-- manifest.c8353bb1e98b372587d9.js.map
|-- vendor.0565b24a91810aaf3061.js
`-- vendor.0565b24a91810aaf3061.js.map
build.js
目录: build/build.js
require('./check-versions')();
process.env.NODE_ENV = 'production';
var ora = require('ora');
var rm = require('rimraf'); //代替物:The UNIX command rm -rf for node.
var path = require('path');
var chalk = require('chalk');
var webpack = require('webpack'); //导入webpack
var config = require('../config'); //导入config目录
var webpackConfig = require('./webpack.prod.conf'); //导入生产配置的webpack配置文件
var spinner = ora('building for production...');
spinner.start();
//每次build都删除一次dist
rm(path.join(config.build.assetsRoot, config.build.assetsSubDirectory), err => {
if (err) throw err;
//调用webpack,导入webpackConfig
webpack(webpackConfig, function (err, stats) {
spinner.stop();
if (err) throw err;
process.stdout.write(stats.toString({
colors: true,
modules: false,
children: false,
chunks: false,
chunkModules: false
}) + '\n\n');
console.log(chalk.cyan(' Build complete.\n'));
console.log(chalk.yellow(
' Tip: built files are meant to be served over an HTTP server.\n' +
' Opening index.html over file:// won\'t work.\n'
));
});
});
webpack.prod.conf
目录: build/webpack.prod.conf.js
var path = require('path');
var utils = require('./utils');
var webpack = require('webpack');
var config = require('../config');
var merge = require('webpack-merge'); //webpack合并模块
var baseWebpackConfig = require('./webpack.base.conf'); //导入基础webpack配置文件
var CopyWebpackPlugin = require('copy-webpack-plugin');
var HtmlWebpackPlugin = require('html-webpack-plugin');
var ExtractTextPlugin = require('extract-text-webpack-plugin'); //单独提取css文件模块
var OptimizeCSSPlugin = require('optimize-css-assets-webpack-plugin');
var env = config.build.env;
//将baseWebpackConfig配置合并
var webpackConfig = merge(baseWebpackConfig, {
module: { //增加模块处理规则
rules: utils.styleLoaders({ //对于所有的css的loader都进行初始化配置
sourceMap: config.build.productionSourceMap,
extract: true
})
},
devtool: config.build.productionSourceMap ? '#source-map' : false, //生成source map文件配置
output: { //输出build生成的js文件
path: config.build.assetsRoot,
filename: utils.assetsPath('js/[name].[chunkhash].js'),//生成主入口文件,如app.js
chunkFilename: utils.assetsPath('js/[id].[chunkhash].js') //生成非主入口文件,如vender.js
},
plugins: [
// http://vuejs.github.io/vue-loader/en/workflow/production.html
new webpack.DefinePlugin({
'process.env': env
}),
new webpack.optimize.UglifyJsPlugin({ //解析/压缩/美化所有的js插件
compress: {
warnings: false
},
sourceMap: true
}),
// extract css into its own file
new ExtractTextPlugin({ //抽离css并且合并到一个文件
filename: utils.assetsPath('css/[name].[contenthash].css')
}),
// Compress extracted CSS. We are using this plugin so that possible
// duplicated CSS from different components can be deduped.
new OptimizeCSSPlugin(), //优化css
// generate dist index.html with correct asset hash for caching.
// you can customize output by editing /index.html
// see https://github.com/ampedandwired/html-webpack-plugin
new HtmlWebpackPlugin({ //生成html文件
filename: config.build.index,
template: 'index.html',
inject: true,
minify: {
removeComments: true,
collapseWhitespace: true,
removeAttributeQuotes: true
// more options:
// https://github.com/kangax/html-minifier#options-quick-reference
},
// necessary to consistently work with multiple chunks via CommonsChunkPlugin
chunksSortMode: 'dependency'
}),
// split vendor js into its own file
new webpack.optimize.CommonsChunkPlugin({ //抽离js中公共的部分并合并到一个文件里
name: 'vendor',
minChunks: function (module, count) {
// any required modules inside node_modules are extracted to vendor
return (
module.resource &&
/\.js$/.test(module.resource) &&
module.resource.indexOf(
path.join(__dirname, '../node_modules')
) === 0
);
}
}),
// extract webpack runtime and module manifest to its own file in order to
// prevent vendor hash from being updated whenever app bundle is updated
new webpack.optimize.CommonsChunkPlugin({ //每次打包但是公共js部分没变的情况下不触发更新这个公共js文件
name: 'manifest',
chunks: ['vendor']
}),
// copy custom static assets
new CopyWebpackPlugin([//将打包后的文件复制到指定目录
{
from: path.resolve(__dirname, '../static'),
to: config.build.assetsSubDirectory,
ignore: ['.*']
}
])
]
});
if (config.build.productionGzip) { //是否打开压缩,这是对整个打包出来的文件夹进行压缩
var CompressionWebpackPlugin = require('compression-webpack-plugin');
webpackConfig.plugins.push(
new CompressionWebpackPlugin({
asset: '[path].gz[query]',
algorithm: 'gzip',
test: new RegExp(
'\\.(' +
config.build.productionGzipExtensions.join('|') +
')$'
),
threshold: 10240,
minRatio: 0.8
})
);
}
if (config.build.bundleAnalyzerReport) {
var BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin;
webpackConfig.plugins.push(new BundleAnalyzerPlugin());
}
module.exports = webpackConfig;
prod.server.js
目录 ./prod.server.js
var express = require('express'); //导入express
var config = require('./config/index'); //导入index.js(里面有很多配置)
var port = process.env.PORT || config.build.port; //初始化端口,端口在index.js配置
var app = express(); //实例化express
var router = express.Router(); //初始化路由
router.get('/',function (req,res,next) {
req.url = '/index.html'; //这里访问的是发布dist/index.html
next();
});
app.use(router);
var appData = require('./data.json'); //读取模拟的数据文件
var seller = appData.seller;
var goods = appData.goods;
var ratings = appData.ratings;
var apiRoutes = express.Router();
apiRoutes.get('/seller', function (req, res) {
res.json({
errno: 0,
data: seller
});
});
apiRoutes.get('/goods', function (req, res) {
res.json({
errno: 0,
data: goods
});
});
apiRoutes.get('/ratings', function (req, res) {
res.json({
errno: 0,
data: ratings
});
});
app.use('/api', apiRoutes);
app.use(express.static('./dist')); //使用./dist作为web目录,所以能够找到.dist/index.html
module.exports = app.listen(port, function (err) { //启动监听
if (err) {
console.log(err);
return
}
console.log('Listening at http://localhost:' + port + '\n')
});