这是我花了几个星期学习webpack4的学习笔记。内容不够细,由于一些相对比较简单的,就随意带过了。但愿文章能给你们带来帮助。若有错误,但愿及时指出。例子都在learn-webpack仓库上。若是你从中有所收获的话,但愿你能给个人github
点个star
。javascript
npm info webpack
查看webpack的历史版本信息等npm init -y
跳过那些选项,默认
全局安装的webpack
: webpack index.js
打包
项目中安装的webpack
: npx webpack index.js
打包script
中脚本打包 : npm run build
命令行中打包:npx webpack index.js -o bundle.js
入口是index.js
, 出口是bundle.js
webpack4
设置mode:production
会压缩代码 development
就不压缩代码
打包 output
里面[name].js loader
中的name
变量 其实就是entry:{main: index.js} 中的key => main
css
devtool: source-map
source-map
: dist
文件夹里会多生成个map
后缀文件,这样页面报错的时候,点击报错后面的地址,会跳转到代码写的地方。而不会跳转到打包后的代码里。inline-source-map
: 不会新生成.map文件,会插入到打包的文件底部cheap-inline-source-map
: 由于inline-source-map
报错会告诉你第几行第几个字符。前面加上cheap
的话 只会告诉你第几行cheap-module-inline-source-map
: 原本map只会映射打包出来的index.js跟业务代码中的关系。第三方引入库报错映射不到。中间加了module这个参数就能够了。好比loader
也会有source-map
开发的时候建议使用:cheap-module-eval-source-map
,eval
表示不会独立生成map文件,而是打包进代码里。
通常development
环境用 cheap-module-eval-source-map
production
环境用cheap-module-source-map
html
// style.css body { color: red; }
当你想给项目添加样式的时候,import ./style.css
导入css
,并执行打包命令的时候。页面并报错vue
ERROR in ./style.css 1:5 Module parse failed: Unexpected token (1:5) You may need an appropriate loader to handle this file type.
这个时候就须要使用loader
来编译了。
安装:npm i style-loader css-loader -D
为何还须要安装style-loader
呢?由于style-loader
会将你的样式经过style
标签插入到页面中
配置webpack.config.js
java
// webpack.config.js const HtmlWebpackPlugin = require('html-webpack-plugin') module.exports = { mode: "development", entry: './index.js', output: { filename: 'bundle.js' }, module: { rules: [ { test: /\.css$/, use: ['style-loader', 'css-loader'] } ] }, plugins: [ new HtmlWebpackPlugin() ] }
上面使用了HtmlWebpackPlugin
是由于我用它来自动生成index.html
方便页面访问node
// package.json "scripts": { "build": "webpack --config webpack.config.js" },
执行npm run build
进行打包,访问dist
目录下的index.html
,能够看到页面显示成功。loader
执行顺序是从下到上,右到左。react
webpack-dev-server
会对你的代码进行打包,将打包的内容放到内存里面,并不会自动给你打包放进dist里。
webpack —watch
页面会刷新下,内容会自动更新
webpack-dev-server
会自动更新当前页面
webpack-dev-server
, 如今的webpack-dev-server
比之前好多了vue-cli3
和react
都是用这个了
devServer: { contentBase: './dist', // 有这个就够了, open: true, // 自动打开浏览器 port: 8080, // 端口没必要填 proxy: {'/api': http://localhost:3000} }
npm install express webpack-dev-middleware -D
在output
中添加publicPath
webpack
const express = require('express') const webpack = require('webpack') const webpackDevMiddleWare = require('webpack-dev-middleware') const config = require('./webpack.config.js') const complier = webpack(config) // 帮咱们作编译的东西,webpack传入config以后会申请一个编译器 app.use(webpackDevMiddleware(complier, { publicPath: config.output.publicPath, // 意思是只要文件改变了,就从新运行 })) const app = express() app.listen(3000, () => { console.log('server is running 3000') })
如今这样子写太麻烦了(vue-cli2也是如此)。由于之前版本
webpack-dev-server
还不够强大,如今不同了。很是的强大了。
热替换,就是不会刷新整个页面。当不使用热更新的时候,操做一些功能,新增了三个元素,修改样式页面自动刷新后,刚才新增的元素会消失。若是开启了热替换,那么原先的dom会还在。
const webpack = require('webpack') // .... devServer: { contentBase: './dist', open: true, hot: true, hotOnly: true // 以防hot失效后,页面被刷新,使用这个,hot失效也不刷新页面 }, // ... plugins: [ new webpack.HotModuleReplacementPlugin() ]
import number from './number.js' if (module.hot) { // 若是热更新存在 // 监听的文件改变,会触发后面的回调方法 module.hot.accept('./number', () => { // dosomething }) }
为何修改了css文件不须要写module.hot。而写js须要写呢,由于css-loader已经自动帮你处理了。
将高版本的js代码转换成低版本的js代码。好比ie浏览器不兼容es6,须要使用babel把es6代码把js转换成低版本的js代码。
安装:npm install --save-dev babel-loader @babel/core
git
module: { rules: [ { test: /\.js$/, exclude: /node_modules/, loader: "babel-loader" } ] }
babel-loader
并不会帮助你把es6语法转换成低级的语法。它只是帮助打通webpack跟babel之间的联系。
转换成es5的语法:
安装:npm install @babel/preset-env --save-dev
@babel/preset-env
包含了es6转换成es5的全部规则。es6
module: { rules: [ { test: /\.js$/, exclude: /node_modules/, loader: "babel-loader", options: { "presets": ["@babel/preset-env"] } } ] }
若是还须要降到更低版本就得使用babel-polyfill
安装:npm install --save @babel/polyfill
页面顶部引入import "@babel/polyfill";
就能够将高级版本语法转换成低级语法。可是直接import
会让打包后的文件很是大。
这个时候就须要再配置webpack.config.js
useBuiltIns
{ test: /\.js$/, exclude: /node_modules/, loader: "babel-loader", options: { // "presets": ["@babel/preset-env"] // 当你作babel-polyfill往浏览器填充的时候,根据业务代码用到什么加什么,并不会所有写入, // 数组中,后面的对象是对数组前面的babel作配置 "presets": [["@babel/preset-env", { useBuiltIns: 'usage' }]] } }
若是开发一个第三方库,类库。使用babel-polyfill
会注入到全局,污染到全局环境。
安装:npm install --save-dev @babel/plugin-transform-runtime
安装:npm install --save @babel/runtime
{ test: /\.js$/, exclude: /node_modules/, loader: "babel-loader", options: { "plugins": ["@babel/plugin-transform-runtime"] } }
当你要添加配置时
{ test: /\.js$/, exclude: /node_modules/, loader: "babel-loader", options: { "plugins": [["@babel/plugin-transform-runtime", { "absoluteRuntime": false, "corejs": false, "helpers": true, "regenerator": true, "useESModules": false }]] } }
若是你要将corejs赋值为2
安装:npm install --save @babel/runtime-corejs2
{ test: /\.js$/, exclude: /node_modules/, loader: "babel-loader", options: { "plugins": [["@babel/plugin-transform-runtime", { "absoluteRuntime": false, "corejs": 2, "helpers": true, "regenerator": true, "useESModules": false }]] } }
@babel/plugin-transform-runtime
不会污染到全局环境。
当babel配置很是多的时候,能够将他们放到.babelrc
文件里
在根目录下建立.babelrc
文件
将options
里的代码放到这个文件中,以下:
{ "plugins": [["@babel/plugin-transform-runtime", { "absoluteRuntime": false, "corejs": 2, "helpers": true, "regenerator": true, "useESModules": false }]] }
安装:npm install --save-dev @babel/preset-react
往刚刚的.babelrc
文件中添加配置
// presets对应一个数组,若是这个值须要作配置,那么这个值在包装进一个数组,放到第一项,第二项是个对象,用于描述该babel { "presets": [ ["@babel/preset-env", { "useBuiltIns": "usage" }], "@babel/preset-react" ] }
注意:转换是先下后上,就是使用preset-react转换react代码,再用preset-env将js代码转换为es5代码