webpack.config.js文件的高级配置
一、多个入口文件
之前我们配置的都是 一个入口
var webpack = require('webpack'); var commonsPlugin = new webpack.optimize.CommonsChunkPlugin('common.js'); module.exports = { //页面入口文件配置 entry: { index: './src/index.js' }, //入口文件输出配置 output: { path: path.join(__dirname, "dist/"), filename: "bundle.js" } };
但是有的 时候我们需要多个入口文件,这个时候该如何配置?
entry 参数支持设置对象,可以设置多个入口文件,这个时候output的filename就不能是固定名字 了,因为入口是多个文件,所以 同时也要修改 output参数:
var webpack = require('webpack'); var commonsPlugin = new webpack.optimize.CommonsChunkPlugin('common.js'); module.exports = { //页面入口文件配置 entry: { app: ['./src/index.js'], login: ['./src/login.js'] }, //入口文件输出配置 output: { path: path.join(__dirname, "dist/"), filename: "bundle_[name].js" } };
这里的filename: "bundle_[name].js" 中的[name]是一个 正则表达式匹配的,这里的[name]名字指的是键值对的键,上面的实例中第一个入口文件是app: ['./src/index.js'],[name]名字对应的是app而不是index。运行一下webapck命令就会在dist生成bundle_app.js和bundle_login.js两个文件
二、plugins插件
常用Plugins介绍
-
代码热替换, HotModuleReplacementPlugin
-
生成html文件,HtmlWebpackPlugin
-
将css成生文件,而非内联,ExtractTextPlugin
-
报错但不退出webpack进程,NoErrorsPlugin
-
代码丑化,UglifyJsPlugin,开发过程中不建议打开
-
多个 html共用一个js文件(chunk),可用CommonsChunkPlugin
-
清理文件夹,Clean
-
调用模块的别名ProvidePlugin,例如想在js中用$,如果通过webpack加载,需要将$与jQuery对应起来
1、CommonsChunkPlugin抽取公共资源
CommonsChunkPlugin 常用参数:
name:与 entry 中的键对应 filename:公共文件的输出名字 minChunks :公共模块被使用的最小次数。比如配置为3,也就是同一个模块只有被3个以外的页面同时引用时才会被提取出来作为common chunks。 minSize:作用类似于minChunks,只不过这里控制的文件大小。
项目中可能会使用很多的第三方插件,如果把所有的插件和自己的js文件,打包成一个js文件,这样网页加载会很慢,并且在优化方面完全可以把第三方插件进行单独的缓存。这个时候就需要把所有的第三方插件单独 打包 为一个js包。CommonsChunkPlugin插件就可以帮助我们实现这个功能。
CommonsChunkPlugin是一个对象,所以使用的时候要 进行实例化
new webpack.optimize.CommonsChunkPlugin('common.js')
CommonsChunkPlugin的参数支持字符串和json
下面我们在webpackDemo中实现CommonsChunkPlugin功能,首先我们通过npm安装 jquery和moment第三方插件:
npm install jquery --save npm install moment --save
接下来在webpack.config.js文件配置CommonsChunkPlugin
var webpack = require('webpack'); var WebpackDevServer = require("webpack-dev-server"); var path = require('path'); var CURRENT_PATH = path.resolve(__dirname); // 获取到当前目录 var ROOT_PATH = path.join(__dirname, '../'); // 项目根目录 var MODULES_PATH = path.join(ROOT_PATH, './node_modules'); // node包目录 var BUILD_PATH = path.join(ROOT_PATH, './dist'); // 最后输出放置公共资源的目录 module.exports = { //项目的文件夹 可以直接用文件夹名称 默认会找index.js ,也可以确定是哪个文件名字 entry: { app: ['./src/index.js'], login: ['./src/login.js'], vendors: ['jquery', 'moment'] //需要打包的第三方插件 }, //输出的文件名,合并以后的js会命名为bundle.js output: { path: path.join(__dirname, "dist/"), publicPath: "http://localhost:8088/dist/", filename: "bundle_[name].js" }, devServer: { historyApiFallback: true, contentBase: "./", quiet: false, //控制台中不输出打包的信息 noInfo: false, hot: true, //开启热点 inline: true, //开启页面自动刷新 lazy: false, //不启动懒加载 progress: true, //显示打包的进度 watchOptions: { aggregateTimeout: 300 }, port: '8088' //设置端口号 }, plugins: [ //new webpack.HotModuleReplacementPlugin() //提取公共部分资源 new webpack.optimize.CommonsChunkPlugin({ // 与 entry 中的 vendors 对应 name: 'vendors', // 输出的公共资源名称 filename: 'common.bundle.js', // 对所有entry实行这个规则 minChunks: Infinity }), ], devtool: 'source-map' };
index.html
由于进行了公共资源的提取,所以页面上 要引入公共部分js文件
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Document</title> </head> <body> <h1 id="welcome">welcome to 68kejian.com</h1> <script src="dist/common.bundle.js"></script> <script src="dist/bundle_app.js"></script> </body> </html>
index.js
var login=require('./login'); var $=require('jquery');//引用jquery模块 $("#welcome").html(login.sayName());
login.js
var userName="68kejian"; module.exports.userName=userName; module.exports.sayName=function(){ return userName; };
这个时候运行webpack执行命令在dist目录下面就会生成如下js文件:
2、ProvidePlugin全局挂载插件
ProvidePlugin插件主要是进行设置全局模块,比如jquery插件几乎所有的页面都用到,使用require('jquery')引用写起来比较多,这个时候就可以使用ProvidePlugin 把jquery设置为全局的, 每个页面就可以 直接使用了。
plugins: [ //new webpack.HotModuleReplacementPlugin() //提取公共部分资源 new webpack.optimize.CommonsChunkPlugin({ // 与 entry 中的 vendors 对应 name: 'vendors', // 输出的公共资源名称 filename: 'common.bundle.js', // 对所有entry实行这个规则 minChunks: Infinity }), // 把jquery作为全局变量插入到所有的代码中 // 然后就可以直接在页面中使用jQuery了 new webpack.ProvidePlugin({ $: 'jquery', jQuery: 'jquery', 'window.jQuery': 'jquery' }), ],
index.js
var login=require('./login'); var data = require('data'); $("#welcome").html(data);
3、自动生成html插件html-webpack-plugin
html-webpack-plugin不是webpack的内置插件所以需要单独安装
npm install html-webpack-plugin --save-dev
html-webpack-plugin插件默认会在打包根目录生成一个index.html页面, 通过相关参数 可以定义输出名字以及其它的相关配置,下面我们看一下相关的参数:
new HtmlWebpackPlugin({ title: 'My App',//设置title的名字 filename: 'admin.html',//设置这个html的文件名 template:'header.html',//要使用的模块的路径 inject: 'body',//把模板注入到哪个标签后 'body' favicon:'./images/favico.ico',//给html添加一个favicon './images/favico.ico' minify:true,//是否压缩 true false hash:true,//是否hash化 true false , cache:false,//是否缓存, showErrors:false,//是否显示错误, xhtml:false //是否自动关闭标签 默认false })
下面我们在webpackDemo项目中加入 这个插件:
var webpack = require('webpack'); var WebpackDevServer = require("webpack-dev-server"); var path = require('path'); var CURRENT_PATH = path.resolve(__dirname); // 获取到当前目录 var ROOT_PATH = path.join(__dirname, '../'); // 项目根目录 var MODULES_PATH = path.join(ROOT_PATH, './node_modules'); // node包目录 var BUILD_PATH = path.join(ROOT_PATH, './dist'); // 最后输出放置公共资源的目录 var HtmlWebpackPlugin = require('html-webpack-plugin'); module.exports = { //项目的文件夹 可以直接用文件夹名称 默认会找index.js ,也可以确定是哪个文件名字 entry: { app: ['./src/js/index.js'], vendors: ['jquery', 'moment'] //需要打包的第三方插件 }, //输出的文件名,合并以后的js会命名为bundle.js output: { path: path.join(__dirname, "dist/"), publicPath: "http://localhost:8088/dist/", filename: "bundle_[name].js" }, devServer: { historyApiFallback: true, contentBase: "./", quiet: false, //控制台中不输出打包的信息 noInfo: false, hot: true, //开启热点 inline: true, //开启页面自动刷新 lazy: false, //不启动懒加载 progress: true, //显示打包的进度 watchOptions: { aggregateTimeout: 300 }, port: '8088' //设置端口号 }, plugins: [ new webpack.HotModuleReplacementPlugin() //提取公共部分资源 new webpack.optimize.CommonsChunkPlugin({ // 与 entry 中的 vendors 对应 name: 'vendors', // // 输出的公共资源名称 filename: 'common.bundle.js', // 对所有entry实行这个规则 minChunks: Infinity }), // 把jquery作为全局变量插入到所有的代码中 // 然后就可以直接在页面中使用jQuery了 new webpack.ProvidePlugin({ $: 'jquery', jQuery: 'jquery', 'window.jQuery': 'jquery' }), //生成index.html页面 new HtmlWebpackPlugin({ title: '68kejian.com', filename: 'index.html', template: 'header.html', inject: 'body', favicon: './images/favico.ico', minify: false, hash: true, cache: false, showErrors: false }) ], externals: { // require('data') is external and available // on the global var data // 'data': 'data' }, devtool: 'source-map' };
header.html
<!DOCTYPE html> <html> <head> <meta http-equiv="Content-type" content="text/html; charset=utf-8"/> <title><%= htmlWebpackPlugin.options.title %></title> </head> <body> </body> </html>
可以看到htmlWebpackPlugin里面的对象通过<%= htmlWebpackPlugin.options.title %>可以打印到页面里面。
运行webpack命令,就会在dist 目录生成了index.html页面
通过截图可以看到html-webpack-plugin会把生成的js文件自动插入到页面中去。
4、提取样式插件extract-text-webpack-plugin
我们 知道webpack使用require()方法可以引用css文件和图片,但是由于它们不像js文件准寻CMD格式, 所有在使用的时候需要通过加载器进行处理。 需要用到两个基本的加载器:css-loader、style.lader,所谓加载器就是一个处理器,它们会把 相关的文件处理为webpack可以使用的规范。加载器不是webpack内置,所有需要npm进行安装,同时,extract-text-webpack-plugin也需要单独安装。
npm install extract-text-webpack-plugin --save-dev npm install css-loader style-loader less-loader
下面是相关配置:
var webpack = require('webpack'); var WebpackDevServer = require("webpack-dev-server"); var path = require('path'); var CURRENT_PATH = path.resolve(__dirname); // 获取到当前目录 var ROOT_PATH = path.join(__dirname, '../'); // 项目根目录 var MODULES_PATH = path.join(ROOT_PATH, './node_modules'); // node包目录 var BUILD_PATH = path.join(ROOT_PATH, './dist'); // 最后输出放置公共资源的目录 var HtmlWebpackPlugin = require('html-webpack-plugin'); var ExtractTextPlugin = require("extract-text-webpack-plugin"); module.exports = { //项目的文件夹 可以直接用文件夹名称 默认会找index.js ,也可以确定是哪个文件名字 entry: { app: ['./src/js/index.js'], vendors: ['jquery', 'moment'] //需要打包的第三方插件 }, //输出的文件名,合并以后的js会命名为bundle.js output: { path: path.join(__dirname, "dist/"), publicPath: "http://localhost:8088/dist/", filename: "bundle_[name].js" }, devServer: { historyApiFallback: true, contentBase: "./", quiet: false, //控制台中不输出打包的信息 noInfo: false, hot: true, //开启热点 inline: true, //开启页面自动刷新 lazy: false, //不启动懒加载 progress: true, //显示打包的进度 watchOptions: { aggregateTimeout: 300 }, port: '8088' //设置端口号 }, module: { loaders: [ // 把之前的style&css&less loader改为 { test: /\.css$/, loader: ExtractTextPlugin.extract('style-loader', 'css-loader'), exclude: /node_modules/ }, { test: /\.less$/, loader: ExtractTextPlugin.extract('style', 'css!less'), exclude: /node_modules/ }, ] }, plugins: [ new webpack.HotModuleReplacementPlugin() //提取公共部分资源 new webpack.optimize.CommonsChunkPlugin({ // 与 entry 中的 vendors 对应 name: 'vendors', // 输出的公共资源名称 filename: 'common.bundle.js', // 对所有entry实行这个规则 minChunks: Infinity }), // 把jquery作为全局变量插入到所有的代码中 // 然后就可以直接在页面中使用jQuery了 new webpack.ProvidePlugin({ $: 'jquery', jQuery: 'jquery', 'window.jQuery': 'jquery' }), //生成index.html页面 new HtmlWebpackPlugin({ title: '68kejian', filename: 'index.html', template: 'header.html', inject: 'body', favicon: './images/favico.ico', minify: false, hash: true, cache: false, showErrors: false }), // 分离css new ExtractTextPlugin('[name].bundle.css', { allChunks: true }), ], externals: { // require('data') is external and available // on the global var data // 'data': 'data' }, devtool: 'source-map' };
代码详解:
module: { loaders: [ // 把之前的style&css&less loader改为 { test: /\.css$/, loader: ExtractTextPlugin.extract('style-loader', 'css-loader'), exclude: /node_modules/ }, { test: /\.less$/, loader: ExtractTextPlugin.extract('style', 'css!less'), exclude: /node_modules/ }, ] }
module对象用来设置加载器的相关配置, loader就是所有加载器的数组。设置加载器的参数如下:
test: /\.css$/,//文件类型,在整个项目 目录 loader: ExtractTextPlugin.extract('style-loader', 'css-loader'),//使用的加载器 exclude: /node_modules/ //排除的目录
ExtractTextPlugin插件的使用和其他的一样,引用、实例化然后在plugins配置。执行webpack命令就会把所有的 js里面引用的css文件抽取到一个css文件里面。
5、拷贝资源插件copy-webpack-plugin
官方这样解释 Copy files and directories in webpack ,在webpack中拷贝文件和文件夹。
需要安装
npm install --save-dev copy-webpack-plugin
相关参数:
from : 定义要拷贝的源目录 __dirname + ‘/src/public’ to : 定义要拷贝的目标目录 __dirname + ‘/dist’ toType : file 或者 dir , 可选,默认是文件 force : 强制覆盖先前的插件 , 可选 默认false context : 不知道作用 , 可选 默认 base context 可用 specific context flatten :只拷贝文件不管文件夹 , 默认是false ignore : 忽略拷贝指定的文件 ,可以用模糊匹配
下面我们对webpackDemo增加一个复制 图片的配置
var webpack = require('webpack'); var WebpackDevServer = require("webpack-dev-server"); var path = require('path'); var CURRENT_PATH = path.resolve(__dirname); // 获取到当前目录 var ROOT_PATH = path.join(__dirname, '../'); // 项目根目录 var MODULES_PATH = path.join(ROOT_PATH, './node_modules'); // node包目录 var BUILD_PATH = path.join(ROOT_PATH, './dist'); // 最后输出放置公共资源的目录 var HtmlWebpackPlugin = require('html-webpack-plugin'); var ExtractTextPlugin = require("extract-text-webpack-plugin"); var CopyWebpackPlugin = require('copy-webpack-plugin'); module.exports = { //项目的文件夹 可以直接用文件夹名称 默认会找index.js ,也可以确定是哪个文件名字 entry: { app: ['./src/js/index.js'], vendors: ['jquery', 'moment'] //需要打包的第三方插件 }, //输出的文件名,合并以后的js会命名为bundle.js output: { path: path.join(__dirname, "dist/"), publicPath: "http://localhost:8088/dist/", filename: "bundle_[name].js" }, devServer: { historyApiFallback: true, contentBase: "./", quiet: false, //控制台中不输出打包的信息 noInfo: false, hot: true, //开启热点 inline: true, //开启页面自动刷新 lazy: false, //不启动懒加载 progress: true, //显示打包的进度 watchOptions: { aggregateTimeout: 300 }, port: '8088' //设置端口号 }, module: { loaders: [ // 把之前的style&css&less loader改为 { test: /\.css$/, loader: ExtractTextPlugin.extract('style-loader', 'css-loader'), exclude: /node_modules/ }, { test: /\.less$/, loader: ExtractTextPlugin.extract('style', 'css!less'), exclude: /node_modules/ }, ] }, plugins: [ new webpack.HotModuleReplacementPlugin() //提取公共部分资源 new webpack.optimize.CommonsChunkPlugin({ // 与 entry 中的 vendors 对应 name: 'vendors', // 输出的公共资源名称 filename: 'common.bundle.js', // 对所有entry实行这个规则 minChunks: Infinity }), // 把jquery作为全局变量插入到所有的代码中 // 然后就可以直接在页面中使用jQuery了 new webpack.ProvidePlugin({ $: 'jquery', jQuery: 'jquery', 'window.jQuery': 'jquery' }), //生成index.html页面 new HtmlWebpackPlugin({ title: '68kejian', filename: 'index.html', template: 'header.html', inject: 'body', favicon: './images/favico.ico', minify: false, hash: true, cache: false, showErrors: false }), // 分离css new ExtractTextPlugin('[name].bundle.css', { allChunks: true }), new CopyWebpackPlugin([ { from: './src/images' } ]) ], externals: { // require('data') is external and available // on the global var data 'data': 'data' }, devtool: 'source-map' };
执行webpack命令就可以拷贝了