webpack就是为打包而生的。css
学习webpack首先须要安装nodejs,而且做者也强调新版本的nodejs会提升webpack的打包速度。
安装好node后就能够在项目命令行中执行下面的代码html
npm init
而后根据须要设置,也能够一直回车,固然若是都使用默认配置也能够node
npm init -y
这样就能够在项目中生成package.json
文件了。这样作的目的就是为了使项目符合node规范。linux
安装webpack有两种方式
1.全局安装webpack(不推荐)
在命令行中输入webpack
npm install webpack webpack-cli -g
安装成功后能够经过命令 webpack -v
查看是否安装成功
可是很是不推荐全局方式安装webpack,由于若是机器上有多项目用不一样版本webpack就没法作到兼容。
全局卸载webpackcss3
npm uninstall webpack webpack-cli -g
2.项目内安装webpack(==推荐==)
命令行进入项目目录,执行下面命令es6
npm install webpack webpack-cli -D
这种方式安装成功后没法经过webpack -v
查看webpack版本信息,由于默认node会查找全局下的webpack。这里就要经过npx命令查看。web
npx webpack -v
npx命令会在当前项目的node_modules
中找到咱们安装的webpack正则表达式
3.安装制定版本webpackchrome
npm install webpack@4.16.0
能够经过webpack info 查看全部版本
安装好webpack后就能够开始打包咱们的项目代码了,如咱们项目中有一个xxx.js
文件。
npx webpack xxx.js
这样就会将某一个js文件进行打包,打包后的文件就存放在项目根目录的dist文件夹中。这样就是webpack最基础的打包方式,使用的也是webpack默认的配置。若是想要更多的功能就要在webpack.config.js
文件中进行配置
在项目根目录中新建一个webpack.config.js
文件。
const path = require('path'); module.exports = { mode: 'production', // 打包模式,production为生产模式,development为开发模式 开发模式下js不会被压缩 // entry: 指定入口文件, entry: { // 打包输出两个文件 home: './src/index.js', index: './src/index.js' }, output: { // 输入配置 publicPath:'http://cdn.com.cn',// 指定打包的文件前缀地址 filename:'[name].js', // 打包后的文件名,可使用placeholder占位符方式,[name]获取到entry中配置的名称 path: path.resolve(__dirname, 'dist') // 打包好的文件夹,默认就是dist } }
这就是最近本的打包配置,指定的打包模式,入口,输出配置等。
配置好后就能够经过
npx webpack
直接运行,不用再写具体文件,而是经过配置的入口去找到指定文件。webpack.config.js
是webpack默认的配置文件,固然也能够手动修改
命令行执行以下面命令便可,npx webpack --config webpackconfig2.js
在平时开发的时候可能不多有人用到npx webpack
这种命令进行打包,这是由于在package.json
文件中对打包命令进行了简化,在scripts中添加以下代码
"scripts": { "bundle": "webpack" },
这样改写后执行npm run bundle
至关于执行了webpack打包命令。
在scripts中使用webpack会优先在项目的node_modules中找webpack。
咱们以前在安装webpack的时候,安装了一个webpack-cli
,这个webpack-cli
包的做用就是让咱们能够在命令行中运行webpack命令(npx webpack
等命令)。
webpack的做用就是打包,可是webpack只能识别js文件,若是咱们的js文件中引入了样式,或者尝试打包一个css文件、图片文件等,那么webpack就会报错。由于webpack不知道如何处理这样的文件。这时webpack就须要一个东西帮他处理,就是loader。
==loader就是帮助webpack打包不能识别的文件==
css-loader & style-loader
const path = require('path'); module.exports = { mode: …… entry: ……, output: ……, module:{ rules:[ { test: /\.css$/, use: ['style-loader','css-loader'] } ] } }
想打包css文件就要安装style-loader和css-loader。
npm install style-loader css-loader -D
rules
数组中就是不少打包规则,经过正则表达式匹配到css文件,而后告诉webpack一旦遇到css文件就使用style-loader
和css-loader
处理。css-loader
的做用是帮助webpack识别css。分析文件关系,而后合并。style-loader
的做用是获得css-loader分析出来的结果,将css挂载到html-header-style中。
==因此loader的调用是有顺序的,顺序是从后向前==,先执行css-loader再执行style-loader。
sass-loader
打包sass文件须要用到sass-loader。首先安装sass-loader和node-sass。npm i sass-loader node-sass -D
而后改动一下rules
rules:[ { test: /\.css$/, use: [ 'style-loader', { loader: 'css-loader', options: { importLoaders: 1, modules: true // 默认false,引入的css属于全局的样式,开启true后,css变为模块化,引入css时能够经过style.xxx } }, 'sass-loader' ] } ]
sass-loader的调用必定要在css-loader
以前,因此要放到数组最后。可是若是一个scss文件中经过import了另外一个scss文件,那么在打包第二个scss文件就会直接走到css-loader
,致使打包失败。因此要在css-loader
的options
中加入importLoaders
,表示走css-loader
前还要走另一个loader。
postcss-loaderpostcss-loader
能够自动添加css3前缀,须要新建一个postcss.config.js
文件,而且要安装插件, npm i autoprefixed -D
将postcss-loader放到rules中sass-loader
以前执行,也就是数组最后。
postcss.config.js
module.exports = { plugins: [require('autoprefixer')] }
这样咱们在打包css代码时,就会自动添加css3前缀。由于autoprefixer中内置了浏览器兼容表,默认>5%兼容。
file-loader & url-loader
先安装npm i file-loader -D
。打包图片文件以下
rules: [ { test: /\.(jpg|png|gif)$/, use: { loader: 'file-loader', option: { name: '[name]_[hash].[ext]', outputPath: 'images/' } } } ]
name命名使用placeholder-占位符
,不指定则打包后的文件是随机生成的名字。
对于特别小的图片,可使用url-loader
打包成base64格式放到js文件中。
先安装npm i url-loader -D
,file-loader的功能url-loader一样也能够实现,经过配置大小限制,若是超过则使用传统方式打包,不然就使用base64方式打包,十分方便。
rules: [ { test: /\.(png|jpg|gif)$/, use:{ loader: 'url-loader', options:{ name: '[name]_[hash].[ext]', outputPath: 'images/', limit: 2048 // 限制文件大小小于2048字节,使用base64方式打包 } } } ]
安装babel-loader 和 babel/core 包。npm i babel-loader @babel/core -D
babel-loader是帮助webpack打包的工具
babel/core是babel的核心库。可让babel识别js中的语法,将js语法转换为AST抽象语法树。
添加babel-loader分析js语法,打通babel和webpack,同时还须要借助其余babel模块才能将es6 转换为 es5。安装babel/preset-envnpm i @babel/preset-env -D
如今就能够将es6转换为es5了,可是一些方法在低版本的浏览器中依然不支持。还须要借助polyfill模块。npm i @babel/polyfill -D
而后在业务代码中引入polyfillimport "@babel/polyfill"
而后改写webpack.config.js
rules: [ { test: /\.js$/, exclude: /node_modules/, // 排除node_modules中的代码 loader: 'babel-loader', options:{ presets:[["@babel/preset-env"],{ targets:{ chrome: ">67" // 能够指定兼容浏览器版本 }, // 当使用polyfill的时候,会将全部特性都加入,而不是根据业务代码决定加什么,致使打包后的文件过大。因此经过以下配置解决这个问题,根据业务代码的须要将使用的特性打包进去 useBuiltIns: 'usage' }] } } ]
如今就能够正常打包es6的代码了。不过依然会有一个潜在的问题,就是polyfill再注入方法的时候经过全局变量的形式完成的,会污染全局环境,不适用组件打包。
解决办法:npm i @babel/plugin-transform-runtime @babel/runtime @babel/runtime-corejs2 -D
在babel options中添加plugins配置。
rules: [ { test: /\.js$/, exclude: /node_modules/, loader: 'babel-loader', options:{ // 库代码使用此配置,解决polyfill的问题 "plugins": [["@babel/plugin-transform-runtime"], { "corejs": 2, "helpers": true, "regenerator": true, "useESModules": false }] } } ]
补充:options内的配置能够单独放到.babelrc文件中
plugin相似一些框架中的生命周期函数,在打包特定的时间点触发去作一些事情。
HtmlWebpackPlugin
如html-webpack-plugin是在打包结束后。安装这个插件。npm i html-webpack-plugin -D
HtmlWebpackPlugin插件会在打包结束后,自动生成一个html文件,并把打包生成的js自动引入到这个html中,html中没有标签。也能够经过模版template,这样在生成html文件时会以配置的html文件为模版生成。
const path = require('path'); module.exports = { mode: …… entry: ……, output: ……, module: ……, plugins: [ new HtmlWebpackPlugin({ // 根据模版生成html文件 template: 'src/index.html' }) ] }
CleanWebpackPlugin
CleanWebpackPlugin插件会在打包前将dist目录删除(非官方)cnpm i clean-webpack-plugin -D
module.exports = { mode: …… entry: ……, output: ……, module: ……, plugins: [ // 从新打包先删除dist目录 new CleanWebpackPlugin(['dist']) ] }
sourceMap 是一个映射关系,他知道dist目录下main.js文件出错位置,对应的是src下的index.js文件的位置。在webpack.config.js中添加devtool配置。
module.exports = { mode: …… devtool: 'none' }
设置devtool: 'none'
,js报错只会提示在打包后的js文件中,在开发的时候定位错误就变得异常困难。
设置devtool: 'source-map'
,js报错会显示在原来的文件中,由于在打包后的目录中会生成一个map.js文件,里面存的就是映射关系。报错时经过映射关系找到原文件。
设置devtool: 'inline-source-map'
,inline这种方式不会生成map文件,而是生成base64字符串保存在打包后的js文件底部。
设置devtool: 'cheap-source-map'
,如不设置cheap,报错信息会具体到行列,致使映射关系复杂,耗费性能。加上cheap解决这个问题,同时不去处理第三方代码,只处理业务代码。到一些业务须要将咱们本身写的模块或者第三方代码进行处理。那就要用到module。
设置devtool: 'cheap-module-source-map'
,设置module后解决cheap不处理第三方模块的问题。
设置devtool: 'cheap-module-eval-source-map'
,设置eval后,不会生成map文件,也不会有base64编码的字符串,而是改变代码的执行方式,经过sourceURL指向原文件。性能最好。
==开发环境最佳实践==:devtool: 'cheap-module-eval-source-map'
==生产环境最佳实践==:devtool: 'cheap-module-source-map'
每次修改后都要从新手动打包,这样很是浪费时间。有三种方式解决这个问题
1.在package.json中添加"watch": "webpack --watch"
scripts:{ "watch": "webpack --watch" }
打包的时候运行命令npm run watch
这时webpack就会监听要打包的文件,若是文件变化就会从新打包。
2.配置 devServer
安装dev-server 执行。npm i webpack-dev-server -D
在package.json中添加配置
scripts:{ "start": "webpack-dev-server" }
打包的时候运行命令npm run start
同时也能够在webpack.config.js中添加配置,
module.exports = { …… devServer: { contentBase: './dist', // 打包文件目录 open: true, // 是否自动打开浏览器 prot: 8080 // 启动服务端口 } }
==webpack-dev-server 打包后不会生成dist目录,而是在内存中。提高打包速度==
使用dev-server时能够搭配使用Hot Module Replacement (热模块替换)
引入HotModuleReplacementPlugin插件,可开启hmr功能,hmr能够热更js、css等代码。
module.exports = { …… devServer: { contentBase: './dist', // 打包文件目录 open: true, // 是否自动打开浏览器 prot: 8080, // 启动服务端口 hot: true, // 开启hmr hotOnly: true // 阻止浏览器自动刷新 }, plugins: [ new webpack.HotModuleReplacementPlugin() ], }
3.本身编写node服务
本身编写服务如server.js ,在package.json中配置server命令"server": "node server.js"
,至关于在node中使用webpack
打包时执行命令npm run server
便可。
webpack基础用法就是这些,文中涉及到的内容足够知足一个小型项目的打包需求。基础用法熟练掌握后,能够经过阅读webpack官方文档进行更详细的打包配置。