上一篇文章介绍了目前前端比较流行的各类编辑器,以及各类流行的打包方式,最后给了一个Gulp的例子,这个例子仍是14年的时候写的,还有一些能够优化的空间,就不讨论了,这篇文章主要讲目前火热的打包构建方式--Webpack的使用方式。css
其实Webpack的入门指导文章很是多,配置方式也各有各样,这里我推荐题叶大神的入门级指南--Webpack 入门指迷,若是不知道Webpack是什么或者不是很清楚各项配置含义的开发者,能够看此文章扫扫盲。毕竟我这篇文章并非特别基础。html
var path = require('path')
var baseConfig = {
resolve: {
extensions: ['', '.js'],
fallback: [path.join(__dirname, '../node_modules')],
alias: {
'src': path.resolve(__dirname, '../src'),
'assets': path.resolve(__dirname, '../src/assets'),
'components': path.resolve(__dirname, '../src/components')
}
},
module: {
loaders: [{
test: /\.js$/,
loader: 'babel',
exclude: /node_modules/
}, {
test: /\.(png|jpe?g|gif|svg|woff2?|eot|ttf|otf)(\?.*)?$/,
loader: 'url?limit=8192&context=client&name=[path][name].[hash:7].[ext]'
},
{
test: /\.css$/,
loader: 'style!css!autoprefixer',
},
{
test: /\.scss$/,
loader: 'style!css!autoprefixer!sass'
}]
}
};
module.exports = baseConfig;复制代码
解读下这个基本配置:前端
一、resolve 解析模块依赖的时候,受影响的配置项。vue
二、module 解析不一样文件使用哪些loader,这个比较简单,不少文章都有,就很少说了,注意的是,这里的scss能够换成你本身的预编译器,例如:sass、less、stylus等,或者直接用postcss都行,固然还能够用一种通用方法,后面补上。node
var webpack = require('webpack');
var path = require('path')
var merge = require('webpack-merge')
var baseConfig = require('./webpack.base')
var getEntries = require('./getEntries')
var hotMiddlewareScript = 'webpack-hot-middleware/client?reload=true';
var assetsInsert = require('./assetsInsert')
module.exports = merge(baseConfig, {
entry: getEntries(hotMiddlewareScript),
devtool: '#eval-source-map',
output: {
filename: './[name].[hash].js',
path: path.resolve('./dist'),
publicPath:'./dist'
},
plugins: [
new webpack.DefinePlugin({
'process.env': {
NODE_ENV: '"development"'
}
}),
new webpack.optimize.OccurenceOrderPlugin(),
new webpack.HotModuleReplacementPlugin(),
new webpack.NoErrorsPlugin(),
new assetsInsert()
]
})复制代码
说说这个配置中的一些难点:react
一、getEntries 是用来配置入口文件,通常不少人是本身手写,或者SPA页面,只有一个入口, 很容易就写出来,可是公司中,不少状况,是须要多入口,也就是多路由的Url,这个时候入口的配置就比较麻烦,我这里是放单独一个文件里面配置,咱们公司是靠规定来执行,也就是一个文件夹全部的main.js都认为是入口文件,其余都忽略。webpack
function getEntry(hotMiddlewareScript) {
var pattern = paths.dev.js + 'project/**/main.js';
var array = glob.sync(pattern);
var newObj = {};
array.map(function(el){
var reg = new RegExp('project/(.*)/main.js','g');
reg.test(el);
if (hotMiddlewareScript) {
newObj[RegExp.$1] = [el, hotMiddlewareScript];
} else {
newObj[RegExp.$1] = el;
}
});
return newObj;
}复制代码
二、assetsInsert 是用来作模板替换的,一个小插件把template里面的值替换成打包后的css或者js。git
var webpack = require('webpack');
var path = require('path')
var merge = require('webpack-merge')
var baseConfig = require('./webpack.base')
var getEntries = require('./getEntries')
var ExtractTextPlugin = require('extract-text-webpack-plugin');
var assetsInsert = require('./assetsInsert')
var productionConf = merge(baseConfig, {
entry: getEntries(),
output: {
filename: './[name].[hash].js',
path: path.resolve('./public/dist'),
publicPath: './'
},
plugins: [
new webpack.DefinePlugin({
'process.env': {
NODE_ENV: '"production"'
}
}),
new ExtractTextPlugin('./[name].[hash].css', {
allChunks: true
}),
new webpack.optimize.UglifyJsPlugin({
compress: {
warnings: false
}
}),
new webpack.optimize.OccurenceOrderPlugin(),
new assetsInsert()
]
})
productionConf.module.loaders = [
{
test: /\.js$/,
loader: 'babel',
exclude: /node_modules/
}, {
test: /\.(png|jpe?g|gif|svg|woff2?|eot|ttf|otf)(\?.*)?$/,
loader: 'url?limit=8192&context=client&name=[path][name].[hash:7].[ext]'
},
{
test: /\.css$/,
loader: ExtractTextPlugin.extract('style', 'css'),
},
{
test: /\.scss$/,
loader: ExtractTextPlugin.extract('style', 'css!sass')
}]
module.exports = productionConf复制代码
基本跟开发的差很少,差异在于: 一、使用ExtractTextPlugin 来打包css,因此要干掉原来base的loaders,从新写了一个,在最下面。github
二、UglifyJsPlugin 给js压缩代码。其余没有什么好解释的了,同样的。web
require('shelljs/global')
env.NODE_ENV = 'production'
var ora = require('ora')
var webpack = require('webpack')
var webpackConfig = require('./webpack.production.config')
var spinner = ora('building for production...')
spinner.start()
var staticPath = __dirname + '/../public/dist/'
rm('-rf', staticPath)
mkdir('-p', staticPath)
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')
})复制代码
写一个build.js,而后在package.json里面添加 script 参数
"build": "node build.js"//这里记得写本身build.js路径复制代码
上面的配置是能够更改的,例如你在loaders 里面加上
{
test: /\.vue$/,
loader: 'vue'
}复制代码
就能够变成支持.vue文件的vuejs打包构建,同理,修改下支持jsx,和添加一些reactjs的module,就能够用来跑Reactjs的东西。
还有能够随意更改Css预编译器的类型,用你本身喜欢就行,或者跟咱们前面提到的方法,把全部类型都配置上,
var path = require('path')
var config = require('../config')
var ExtractTextPlugin = require('extract-text-webpack-plugin')
exports.assetsPath = function (_path) {
return path.posix.join(config.build.assetsSubDirectory, _path)
}
exports.cssLoaders = function (options) {
options = options || {}
// generate loader string to be used with extract text plugin
function generateLoaders (loaders) {
var sourceLoader = loaders.map(function (loader) {
var extraParamChar
if (/\?/.test(loader)) {
loader = loader.replace(/\?/, '-loader?')
extraParamChar = '&'
} else {
loader = loader + '-loader'
extraParamChar = '?'
}
return loader + (options.sourceMap ? extraParamChar + 'sourceMap' : '')
}).join('!')
if (options.extract) {
return ExtractTextPlugin.extract('vue-style-loader', sourceLoader)
} else {
return ['vue-style-loader', sourceLoader].join('!')
}
}
// http://vuejs.github.io/vue-loader/configurations/extract-css.html
return {
css: generateLoaders(['css']),
postcss: generateLoaders(['css']),
less: generateLoaders(['css', 'less']),
sass: generateLoaders(['css', 'sass?indentedSyntax']),
scss: generateLoaders(['css', 'sass']),
stylus: generateLoaders(['css', 'stylus']),
styl: generateLoaders(['css', 'stylus'])
}
}
// Generate loaders for standalone style files (outside of .vue)
exports.styleLoaders = function (options) {
var output = []
var loaders = exports.cssLoaders(options)
for (var extension in loaders) {
var loader = loaders[extension]
output.push({
test: new RegExp('\\.' + extension + '复制代码
), loader: loader }) } return output }
这就是把全部的css预编译的都加到配置里面了。
Webpack多种多样,就算一个loaders都有好几种不一样的配置,让人非常头疼,最关键的是不少插件本身的文档也不清不楚,弄得你们都很迷茫,个人经验就是多试多测,本身多写一写,看命令行打印的错误,去找缘由,不要一看到报错就慌了,不少新手最容易犯错就是一看到报错就怀疑人生了,必定要看报错记录,通常都有提示,按照提示去解决相应问题就好啦。
下一章咱们讲Nodejs的东东。