webpack4.0刚刚发布,官网自称4.0最大的特色就是零配置。本文就详细介绍一下webpack4.0实战那些事儿。javascript
打包机
WebPack能够看作是模块打包机:它作的事情是,分析你的项目结构,找到JavaScript模块以及其它的一些浏览器不能直接运行的拓展语言(Scss,TypeScript等),并将其打包为合适的格式以供浏览器使用。css
构建
构建就是把源代码转换成发布到线上的可执行 JavaScrip、CSS、HTML 代码,包括以下内容。html
构建实际上是工程化、自动化思想在前端开发中的体现,把一系列流程用代码去实现,让代码自动化地执行这一系列复杂的流程。 构建给前端开发注入了更大的活力,解放了咱们的生产力。前端
npm init -y
在要进行打包的目录下初始化npm, 在控制台执行以上命令后会生成一个package.json
的文件。java
npm install webpack webpack-cli -D
由于从4.0开始,webpack拆分开两个包分别是webpack
和webpack-cli
node
webpack.config.js
module.exports = { entry:配置入口文件的地址 output:配置出口文件的地址 module:配置模块,主要用来配置不一样文件的加载器 plugins:配置插件 devServer:配置开发服务器 }
接下来咱们就一一介绍一下它们的配置。react
npm install webpack-dev-server -D
devServer:{ contentBase:path.resolve(__dirname,'dist'),// 配置开发服务运行时的文件根目录 host:'localhost',// 开发服务器监听的主机地址 compress:true, // 开发服务器是否启动gzip等压缩 port:8080 // 开发服务器监听的端口 }
"scripts": { "dev": "webpack-dev-server --open --mode development " }
note
从4.0开始,运行webpack时必定要加参数 --mode development
或者--mode production
,分别对应开发环境和生产环境。jquery
module
loader
module
主要用来配置不一样文件的加载器。谈到加载就离不开loader
,那什么是loader
呢?webpack
loader的概念
经过使用不一样的Loader,Webpack能够要把不一样的文件都转成JS文件,好比CSS、ES6/七、JSX等。git
test
:匹配处理文件的扩展名的正则表达式use
:loader名称,就是你要使用模块的名称include/exclude
:手动指定必须处理的文件夹或屏蔽不须要处理的文件夹query
:为loaders提供额外的设置选项
loader
的三种写法
install
npm install style-loader css-loader -D
配置加载器
module: { rules:[ { test:/\.css$/, use:['style-loader','css-loader'], include:path.join(__dirname,'./src'), exclude:/node_modules/ } ] }
note
注意:加载器的加载顺序为从右至左。即先用css-loader
解析而后用style-loader
将解析后的css
文件添加到Head
标签中。
install
npm install file-loader url-loader html-withimg-loader -D
file-loader
解决CSS等文件中的引入图片路径问题url-loader
当图片较小的时候会把图片BASE64编码,大于limit参数的时候仍是使用file-loader 进行拷贝配置加载器
{ test: /\.(png|jpg|gif|svg|bmp|eot|woff|woff2|ttf)$/, loader: { loader: 'url-loader', options: { limit: 5 * 1024,// 图片大小 > limit 使用file-loader, 反之使用url-loader outputPath: 'images/'// 指定打包后的图片位置 } } }
usage - 手动添加图片
let logo = require('./images/logo.png'); let img = new Image(); img.src = logo; document.body.appendChild(img);
usage - 在CSS中引入图片
.img-bg{ background: url(./images/logo.png); width:173px; height:66px; }
usage - 在HTML中使用图片
{ test:/\.(html|html)$/, use:'html-withimg-loader', include:path.join(__dirname,'./src'), exclude:/node_modules/ }
npm install less less-loader node-sass sass-loader -D
把编译好的代码放到head里面
{ test: /\.css$/, loader: ['style-loader', 'css-loader'] }, { test: /\.less$/, loader: ['style-loader', 'css-loader'] }, { test: /\.scss$/, loader: ['style-loader', 'css-loader'] }
把编译好的代码放到单独的文件里面
const ExtractTextWebpackPlugin = require('extract-text-webpack-plugin'); let cssExtract = new ExtractTextWebpackPlugin('css.css'); let lessExtract = new ExtractTextWebpackPlugin('less.css'); let sassExtract = new ExtractTextWebpackPlugin('sass.css'); ... { test: /\.css$/, loader: cssExtract.extract({ use: ['css-loader?minimize'] }) }, { test: /\.less$/, loader: lessExtract.extract({ use: ['css-loader?minimize', 'less-loader'] }) }, { test: /\.scss$/, loader: sassExtract.extract({ use: ['css-loader?minimize', 'sass-loader'] }) }
为了浏览器的兼容性,有时候咱们必须加入-webkit,-ms,-o,-moz这些前缀
install
npm install postcss-loader autoprefixer -D
usage
postcss-loader
须要配置 postcss.config.js
文件,postcss.config.js 内容以下:
module.exports = { plugins: [ require('autoprefixer') ] }
// 把 post-laoder push 到css的loader数组中 { test: /\.css$/, loader: ['style-loader', 'css-loader', 'postcss-loader'] }, { test: /\.less$/, loader: ['style-loader', 'css-loader', 'less-loader'] }, { test: /\.scss$/, loader: ['style-loader', 'css-loader', 'sass-loader'] }
Babel实际上是一个编译JavaScript的平台,能够把ES6/ES7,React的JSX转义为ES5。
install
npm i babel-core babel-loader babel-preset-env babel-preset-stage-0 babel-preset-react -D
配置加载器
{ test:/\.jsx?$/, use: { loader: 'babel-loader', options: { presets: ["env","stage-0","react"]// env --> es6, stage-0 --> es7, react --> react } }, include:path.join(__dirname,'./src'), exclude:/node_modules/ }
plugins
配置插件
咱们但愿自动能产出HTML文件,并在里面引入产出后的资源。
install
npm install html-webpack-plugin -D
usage
const HtmlWebpackPlugin = require('html-webpack-plugin'); plugins: [ new HtmlWebpackPlugin({ template: './src/index.html', // 指定产出的模板 filename: 'base.html', // 产出的文件名 chunks: ['common', 'base'], // 在产出的HTML文件里引入哪些代码块 hash: true, // 名称是否哈希值 title: 'base', // 能够给模板设置变量名,在html模板中调用 htmlWebpackPlugin.options.title 能够使用 minify: { // 对html文件进行压缩 removeAttributeQuotes: true // 移除双引号 } }) ]
由于CSS的下载和JS能够并行,当一个HTML文件很大的时候,咱们能够把CSS单独提取出来加载
install
npm install extract-text-webpack-plugin@next -D
usage
const ExtractTextWebpackPlugin = require('extract-text-webpack-plugin'); let cssExtract = new ExtractTextWebpackPlugin('css.css'); let lessExtract = new ExtractTextWebpackPlugin('less.css'); let sassExtract = new ExtractTextWebpackPlugin('sass.css'); ... module: { rules: [ { test: /\.css$/, loader: cssExtract.extract({ use: ['css-loader?minimize'] }) }, { test: /\.less$/, loader: lessExtract.extract({ use: ['css-loader?minimize', 'less-loader'] }) }, { test: /\.scss$/, loader: sassExtract.extract({ use: ['css-loader?minimize', 'sass-loader'] }) } ] } ... plugins: [ cssExtract, lessExtract, sassExtract ]
处理图片路径问题
const PUBLIC_PATH='/'; output: { path: path.resolve(__dirname, 'dist'), filename: 'bundle.js', publicPath:PUBLIC_PATH }
有时项目中没有引用的文件也须要打包到目标目录
install
npm install copy-webpack-plugin -D
usage
const CopyWebpackPlugin = require('copy-webpack-plugin'); plugins: [ new CopyWebpackPlugin([{ from: path.join(__dirname, 'public'), // 从哪里复制 to: path.join(__dirname, 'dist', 'public') // 复制到哪里 }]) ]
install
npm install clean-webpack-plugin -D
usage
const CleanWebpackPlugin = require('clean-webpack-plugin'); plugins: [ new CleanWebpackPlugin([path.join(__dirname, 'dist')]) ]
install
npm install uglifyjs-webpack-plugin -D
usage
onst UglifyjsWebpackPlugin = require('uglifyjs-webpack-plugin'); plugins: [ new UglifyjsWebpackPlugin() ]
webapck经过配置能够自动给咱们source maps文件,map文件是一种对应编译文件和源文件的方法
usage
devtool:'eval-source-map'
devtool的参数详解
source-map
把映射文件生成到单独的文件,最完整最慢cheap-module-source-map
在一个单独的文件中产生一个不带列映射的Mapeval-source-map
使用eval打包源文件模块,在同一个文件中生成完整sourcemapcheap-module-eval-source-map
sourcemap和打包后的JS同行显示,没有映射列import _ from 'lodash'; alert(_.join(['a','b','c'],'@'));
new webpack.ProvidePlugin({ _:'lodash' })
当代码发生修改后能够自动从新编译
watch: true, watchOptions: { ignored: /node_modules/, //忽略不用监听变动的目录 aggregateTimeout: 500, // 文件发生改变后多长时间后再从新编译(Add a delay before rebuilding once the first file changed ) poll:1000 //每秒询问的文件变动的次数 }
若是你有单独的后端开发服务器 API,而且但愿在同域名下发送 API 请求 ,那么代理某些 URL 会颇有用。
//请求到 /api/users 如今会被代理到请求 http://localhost:9000/api/users。 proxy: { "/api": "http://localhost:9000", }
指定extension以后能够不用在require或是import的时候加文件扩展名,会依次尝试添加扩展名进行匹配
resolve: { //自动补全后缀,注意第一个必须是空字符串,后缀必定以点开头 extensions: ["",".js",".css",".json"], },
配置别名能够加快webpack查找模块的速度
const bootstrap = path.join(__dirname,'node_modules/bootstrap/dist/css/bootstrap.css'); resolve: { alias: { 'bootstrap': bootstrap } }
install
npm install expose-loader -D
action
把模块的导出暴露给全局变量,
usage-1
require("expose-loader?libraryName!./file.js");
usage-2
rules: [{ test: require.resolve('jquery'),// 注意 这里是require的resolve 方法 use: { loader: "expose-loader", options: "$" } }]
有时候咱们的页面能够不止一个HTML页面,会有多个页面,因此就须要多入口
usage
// 多个入口,能够给每一个入口添加html模板 entry: { index: './src/index.js', main:'./src/main.js' }, output: { path: path.resolve(__dirname, 'dist'), filename: '[name].[hash].js', publicPath:PUBLIC_PATH }, plugins: [ new HtmlWebpackPlugin({ minify: { removeAttributeQuotes:true }, hash: true, template: './src/index.html', chunks:['index'], filename:'index.html' }), new HtmlWebpackPlugin({ minify: { removeAttributeQuotes:true }, hash: true, chunks:['login'], template: './src/login.html', filename:'login.html' })] ]
若是咱们想引用一个库,可是又不想让webpack打包,而且又不影响咱们在程序中以CMD、AMD或者window/global全局等方式进行使用,那就能够经过配置externals。
webpack.config.js
externals: { jquery: "jQuery" //若是要在浏览器中运行,那么不用添加什么前缀,默认设置就是global },
index.js
const $ = require("jquery"); const $ = window.jQuery;