作者:余韵之
webpack目前是前端罕用的工程化工具了。它能够帮忙咱们自动化构建打包各类的资源,极大的进步了咱们打包代码的效率。在webpack看来,所有的资源文件都是模块(module),只是解决的形式不同。
一、初探webpack
1、装置webpack
倡议不要全局装置webpack,因为不同的我的项目webpack的版本号是不一样的。这样多个我的项目来回切换是很不不便的。
npm install wepack webpack-cli -g在我的项目内装置webpack
npm install wepack webpack-cli -D留神:webpack-cli的作用是咱们能够在命令行里间接应用webpack
查看版本
npx webpack -v查看 webpack 所有能够装置的版本号
npm info webpack2、最简略的webpack.config.js的配置
const path = require('path');module.exports = { entry: { main:'./src/index.js' }, output: { filename: 'main.js', path: path.resolve(__dirname, 'dist') }}这段配置是通知咱们:
- 咱们须要打包入口文件是./src/index.js,
- 最初输入的打包文件是在当前目录下dist/main.js
- 如果存在bundle/index.html,就能够通过script引入main.js文件了。当然这个也能够通过webpack自动化构建。
3、两种打包形式
1) npx
npx webpacknpx 示意会在当前目录里寻找依赖变量 webpack
2) script
在package.json里配置
"scripts": { "bundle": "webpack"},于是能够运行
npm run bundle运行 npx webpack / npm run bundle 会先查看是否有配置文件webpack.config.js,如果没有就走默认配置,如果有就走配置文件
4、打包的参数详解
- Hash:示意这一次打包的惟一标识值
- Version:示意这一次打包的应用版本
- Time:示意以后打包整体耗时
- Asset:示意此次打包呈现了bundle.js
- Size:示意该文件的大小
- Chunk Names 示意的是 entry里入口的key,默认为main,也能够任意改为 xxx,yyy
- Entrypoint main = bundle.js 示意入口文件 以及顺次打包的文件0[2]……
二、应用Loader打包资源
1、什么是loader?
webpack不能辨认非js的模块,须要对于不同的模块提供不同的打包计划,于是要求助于loader。如:css-loader、sass-loader、file-loader、vue-loader、postcss-loader等等
2、打包图片
file-loader实现原理思路: 当发现代码引入图片模块,首先把图片挪动到dist目录下并改了名字,失去了绝对于dist的地址,作为返回值给到咱们引入的变量之中
module.exports = { entry: { main: './src/index.js' }, module: { rules: [{ test: /\.(jpg|png)$/, use: { loader: 'file-loader', options: { name: '[name]_[hash].[ext]', // [name] [hash] [ext] 均为占位符 outputPath: 'images/', // 打包出的后果放在images/目录下 limit: 10240 } } }] }, output: { filename: 'main.js', path: path.resolve(__dirname, 'dist') }}3、打包CSS 或 SASS
- css-loader:会帮咱们剖析几个css的关系(相互引入)合并成一个css
- style-loader:当css-loader合并成了一个css,style-loader会把内容挂载到head局部
- sass-loader:解析sass成css
- postcss-loader:主动增加-webkit等前缀,兼容不同浏览器款式
应用了postcss-loader,须要在根目录创立postcss.config.js
module.exports = { plugins: [ require('autoprefixer') ]}webpack.config.js中module配置
module: { rules: [ { test: /\.(jpg|png|gif)$/, use: { loader: 'url-loader', options: { name: '[name]_[hash].[ext]', outputPath: 'images/', limit: 10240 } } }, { test: /\.(eot|ttf|svg)$/, use: { loader: 'file-loader' } }, { test: /\.scss$/, use: [ 'style-loader', { loader: 'css-loader', options: { importLoaders: 2 } }, 'sass-loader', 'postcss-loader' ] }] },Loader解析是有先后顺序的:从下到上,从右到左
4、CSS modules
{ test: /\.scss$/, use: [ 'style-loader', { loader: 'css-loader', options:{ importLoaders: 2,// 示意scss文件导入了scss文件仍然走postcss-loader sass-loader modules:true // 开启css模块化 } }, 'sass-loader', 'postcss-loader' ]}modules开启为true后,就能够应用模块化CSS互不烦扰。否则引入的CSS或者SASS的代码会造成全局净化
应用形式如下
import style from './index.scss’;var img = new Image();img.src = avatar;img.classList.add(style.avatar);5、打包字体
在webpack.config.js配置
{ test: /\.(eot|ttf|svg)$/, use: { loader: 'file-loader' } },三、应用Plugins打包便捷
1、什么是Plugins?
plugins是在某个时刻(刚打包、打包完结,打包两头)做一件事
2、html-webpack-plugin
在打包完结时,在dist主动生成html,并且把打包的main.js主动引入html的script的标签
3、clean-webpack-plugin
在每次打包生成的dist文件前,先删除外面的内容
4、装置及配置两个plugin
npm install html-webpack-plugin clean-webpack-plugin -Dwebpack.config.js
const HtmlWebpackPlugin = require('html-webpack-plugin');const CleanWebpackPlugin = require('clean-webpack-plugin’);plugins: [new HtmlWebpackPlugin({ template: 'src/index.html' // 参考模板为 src/index.html}), new CleanWebpackPlugin(['dist'])],还有其余的plugins,比方热更新 HotModuleReplacementPlugin ……
前面缓缓加上和介绍
四、Entry 和 Output 配置
后面的都是单入口,单进口的配置。
1、多入口,多进口
entry: { main: './src/index.js’, sub: ‘./src/index.js'},plugins: [new HtmlWebpackPlugin({ template: 'src/index.html'}), new CleanWebpackPlugin(['dist'])],output: { filename: '[name].js', path: path.resolve(__dirname, 'dist')}最初的后果是html 里会引入两个js文件
<script scr=“./main.js"></script><script scr=“./sub.js"></script>2、把打包的JS上传到CDN
entry: { main: './src/index.js’, sub: ‘./src/index.js'},plugins: [new HtmlWebpackPlugin({ template: 'src/index.html'}), new CleanWebpackPlugin(['dist'])],output: { publicPath: 'http://cdn.com.cn', // 最初打包进去是http://cdn.com.cn、main.js filename: '[name].js', path: path.resolve(__dirname, 'dist')}html引入的script 会主动加上publicPath门路
<script scr=“http://cdn.com.cn/main.js"></script><script scr=“http://cdn.com.cn/sub.js"></script>五、SourceMap
1、什么是SourceMap
先举个例子:
关上浏览器发现代码报错了。。。。当初晓得dist目录下main.js 文件 96行出错。
用了sourceMap之后(它是一个映射关系),于是晓得dist目录下main.js文件96行实际上对应的是src目录下index.js文件中的第1行
应用了sourceMap 打包速度是会变慢的。同时dist里多了一个xx.js.map文件,原理一个vlq汇合
2、配置SourceMap
在webpack.config.js 里 devtool
devtool: 'cheap-module-eval-source-map',罕用的几个source-map的前缀:
- Inline:inline-source-map 是把xx.js.map内容间接打包到xx.js里,用data url模式的形式放在开端,会通知你第几行第几列除了问题,很消耗性能
- Cheap:增加cheap-inline-source-map 能够准确到每一行不准确到每一列出错 ,能够升高打包工夫,进步性能
- Module:如果要管第三方模块代码的映射能够加上module,能够加上cheap-module-inline-source-map
- Eval:eval是打包最快的形式 ,通过eval是执行效率最快、性能最好的形式,然而如果代码简单的话,提醒的内容可能不够全面,用eval的形式执行JS代码
3、最佳实际
开发环境:提醒全,打包速度快
mode: 'development',devtool: 'cheap-module-eval-source-map',生产环境:提醒成果会更好
mode: 'production',devtool: 'cheap-module-source-map',六、webpackDevServer
1、如何解决每次手动打包,手动启动浏览器刷新页面更新代码?
- webpack —watch
在package.json 里 script 增加
"watch": "webpack --watch"长处:监听到源代码扭转,会主动打包
毛病:须要手动刷新页面
- webpack-dev-server
在package.json 里 script 增加
"start": "webpack-dev-server",在devDependencies装置
"webpack-dev-server": "^3.1.10"长处:监听到源代码扭转,会主动打包,主动启动服务器,自动更新浏览器
留神应用了webpack-dev-server打包后就不会目录里有dist了,而是放在电脑某个内存里,能够提高效率。
2、如何启动时主动关上浏览器
在webpack.config.js配置
devServer: { contentBase: './dist', open: true, // 默认启动开启浏览器 port: 8080, // 端口设置为8080},七、热更新 HMR(HOT MODULE REPLACE)
如果只是纯正应用了webpack-dev-server那么当扭转了代码,浏览器会主动刷新初始化数据。有时候比拟麻烦。
有没有什么方法能够做到:
当批改了css只扭转css的款式,js新增的数据不变。
此时把背景色改成红色
或者当批改了某一个模块的数据,另一个模块的数据不扭转
配置如下
webpack.config.js
const webpack = require('webpack’);devServer: { contentBase: './dist', open: true, port: 8080, hot: true, // 开启热更新的性能 hotOnly: true // 即便HMR不失效,也不更新浏览器 },plugins: [ new HtmlWebpackPlugin({ template: 'src/index.html' }), new CleanWebpackPlugin(['dist']), new webpack.HotModuleReplacementPlugin() // 配置热更新plugins ],同时必须增加模块更新的代码。例如有两个模块,当扭转了number模块,就更新number,counter模块不扭转
index.js
import counter from './counter';import number from './number';counter();number();if(module.hot) { module.hot.accept('./number', () => { document.body.removeChild(document.getElementById('number')); number(); })}css能够不写 module.hot判断 是因为css-loader曾经实现了。如果一些特地的模块,就须要本人写一个module.hot来判断
八、Babel解决ES6语法
1、装置依赖
npm install —save-dev babel-loader @babel/core @babel/preset-env- babel-loader : 提供辨认模块的打包工具
- @babel/core : 辨认js代码转化为AST形象语法树,编译转化成新的语法
- @babel/preset-env : 把ES6代码转化为ES5语法,提供了翻译规定
2、打包形式
二选一
1)装置@babel/profill
npm install -save-dev @babel/profill毛病:这个会呈现全局净化
配置规定
rules:[{ test: /\.js$/, exclude: /node_modules/, loader: 'babel-loader', options:{ presets: [['@babel/preset-env', { targets: { chrome: "67", }, useBuiltIns: 'usage' // 示意做polyfill 依据业务代码来加对应的代码,能够缩小打包的体积 }]] }}],留神:useBuiltIns: 'usage' 示意按需引入
2)装置 @babel/plugin-transform-runtime
npm install -save-dev @babel/plugin-transform-runtime @babel/runtime @babel/runtime-corejs2长处:可是应用闭包的形式不影响其余环境变量
配置 创立.babelrc
{ "plugins": [["@babel/plugin-transform-runtime", { "corejs": 2, // 应用了2 就须要装置 @babel/runtime-corejs2 "helpers": true, "regenerator": true, "useESModules": false }]]}webpack.config.js
{ test: /\.js$/, exclude: /node_modules/, loader: 'babel-loader'}九、打包React代码
1、装置依赖
@babel/preset-react : 能够解析JSX
npm install --save-dev @babel/preset-reactwebpack.config.js
{ test: /\.js$/, exclude: /node_modules/, loader: 'babel-loader',}创立.babelrc
{ "presets": [ [ "@babel/preset-env", { "targets": { "chrome": "67" }, "useBuiltIns": "usage" } ], "@babel/preset-react" ]}留神:先解析react的语法,而后再把ES6语法解析为ES5。presets是自下而上,自左边而左来解析的
咱们是晓黑板前端,欢送关注咱们的知乎、Segmentfault、CSDN、简书、开源中国、博客园账号。