source map错误提醒
JavaScript 提供了 source map 功能,将编译后的代码映射回原始源代码。这可以帮助我们追踪到错误和警告在源代码中的原始位置。
配置webpack.config.js
module.exports = {
entry: './src/main.js',
devtool: 'inline-source-map',//配置source map
output:{
filename:'bundle.js',
},
};
创建src文件夹和入口文件main.js
function Component(){
var div=document.createElement('div')
div.innerHTML="错误提醒"
consoell.log('我打印一下字');//注意这里我故意把console打错
return div
}
document.body.appendChild(Component())
打开打包后的index.html
,发现浏览器控制台报错并且指示了错误的位置
这时候把错误改回来,发现没有报错且正确输出了
代码分离
代码分离可以用于获取更小的 bundle,以及控制资源加载优先级,如果使用合理,会极大影响加载时间。
有三种常用的代码分离方法:
- 入口起点:使用
entry
配置手动地分离代码。 - 防止重复:使用
CommonsChunkPlugin
去重和分离 chunk。 - 动态导入:通过模块的内联函数调用来分离代码。
1. 入口起点
将想要分离的两个文件设置成两个入口文件
const HTMLWebpackPlugin = require('html-webpack-plugin');
module.exports = {
entry: {
main: './src/main.js',
another: './src/vender.js'
},
output: {
filename: '[name].bundle.js',
},
plugins: [new HTMLWebpackPlugin({title: 'Code Splitting'})],
};
问题:
- 如果入口 chunks 之间包含重复的模块,那些重复模块也会被引入到各个 bundle 中。
- 不够灵活,且不能将核心应用程序逻辑进行动态拆分代码
2. 防止重复
CommonsChunkPlugin
插件可以将公共的依赖模块提取到已有的入口 chunk 中,或者提取到一个新生成的 chunk。这里采取后者,将提取公共部分到新生成的chunk
const HTMLWebpackPlugin = require('html-webpack-plugin');
const webpack=require('webpack')//添加
module.exports = {
entry: {
main: './src/main.js',
another: './src/vender.js'
},
output: {
filename: '[name].bundle.js',
},
plugins: [
new HTMLWebpackPlugin({
title: 'Code Splitting'
}),
new webpack.optimize.CommonsChunkPlugin({
name:'common' //将公共bundle命名为common
})
],
};
3. 动态导入
第一种方式是 import()
语法;第二种是使用 webpack 特定的 require.ensure
。现将配置文件处理一下:
const HTMLWebpackPlugin = require('html-webpack-plugin');
module.exports = {
entry: {
main: './src/main.js',//恢复成一个入口文件
},
output: {
filename: '[name].bundle.js',
chunkFilename: '[name].bundle.js',//chunkFilename决定非入口 chunk 的名称
},
plugins: [new HTMLWebpackPlugin({title: 'Code Splitting'})],
};
import()方式示例
bar.js:假设这是一个需要被导入的文件
export function add(a,b){
return a+b
}
main.js 原本写法
import {add} from './bar.js'
console.log(add(2,3))
main.js import()
写法
import('./bar.js').then(({add})=>{ //生成[id].bundle.js
console.log(add(2,3))
})
打包后发现,import()内的内容会分离到一个单独的bundle
自动编译
每次要编译代码时,手动运行 npm run build
就会变得很麻烦
webpack 中有几个不同的选项,可以帮助你在代码发生变化后自动编译代码:
- webpack's Watch Mode
- webpack-dev-server
- webpack-dev-middleware(不写
1.使用观察模式
在观察模式下,如果其中一个文件被更新,代码将被重新编译。
//在package.json添加脚本**以方便启动观察模式
"scripts": {
"test": "echo "Error: no test specified" && exit 1",
"build": "webpack",
"watch":"webpack --watch" //添加
},
启动观察模式
npm run watch
这时候会看到 webpack 在编译代码,现在只要修改并保存了文件,就会看到webpack 在自动重新编译修改后的模块,如果想关闭观察模式,重新打开项目即可。缺点:需要刷新浏览器才能看到重新编译后的效果
2.使用webpack-dev-server
webpack-dev-server
为提供了一个简单的 web 服务器,并且能够实时重新加载(live reloading)。即重新编译后还会自动帮助我们刷新浏览器
安装
npm install --save-dev webpack-dev-server
配置
//...
module.exports = {
//...
//告知 webpack-dev-server,在 localhost:8080 下建立服务
//并将 dist 目录下的文件,作为可访问文件。
devServer:{
contentBase:'./dist'
}
};
添加脚本
"scripts": {
"test": "echo "Error: no test specified" && exit 1",
"build": "webpack",
"watch":"webpack --watch",
"start":"webpack-dev-server --open" //添加
},
执行命令
npm run start
这个时候会发现它帮我们自动打开浏览器。现在如果修改和保存任意文件,web 服务器就会自动重新加载编译后的代码并呈现新的页面。
如果误关了浏览器,可以随时在终端窗口找到本地链接进行访问
不过在开启Web服务器之前,需要在html-webpack-plugin插件的基础上npm run build自动生成一个index.html,否则启动服务器会看不要预期的页面。这是因为配置上写的是从dist里访问文件,如果dist里面没有该文件自然访问不到了。当然如果本身dist里面就有html,就不需要再build了。
处理样式
分离样式文件
一般来说,在生产环境下,我们希望样式存在于CSS文件中而不是style标签中,因为文件更有利于客户端进行缓存。抽取出来后样式表将不再依赖于 JavaScript。Webpack社区有专门的插件专门用于提取样式到CSS文件的:
- extract-text-webpack-plugin(适用于Webpack 4之前版本)
- mini-css-extract-plugin(适用于Webpack 4及以上版本),
安装
npm install --save-dev mini-css-extract-plugin
示例
//style.css
body {
background: green;
}
//入口main.js
import './style.css';
//webpack.config.js
const MiniCssExtractPlugin = require('mini-css-extract-plugin');//加载
module.exports = {
//...
entry: {main:'./src/main.js'},
plugins: [new MiniCssExtractPlugin()]//使用
module: {
rules: [
{
test: /.css$/,
use: [MiniCssExtractPlugin.loader, 'css-loader'],//使用
},
],
},
};
打包后你会发现多出了一个文件。名称是所以是main,是因为入口文件的chunk name是main。
样式的提取是以资源入口开始的整个chunk为单位的,所以如果有多个入口,需要加上
filename
区分一下,它的书写方式与输出文件(output)基本是一样的。这样,每个入口文件中所依赖的样式文件都会被整合在一个文件中并输出:
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
module.exports = {
//...
plugins: [new MiniCssExtractPlugin({filename:'[name].css'})]
//...
};
样式预处理
样式预处理(loader)指的是在开发中我们经常会使用一些样式预编译语言,如SCSS、Less等,在项目打包过程中再将这些预编译语言转换为CSS。
sass和scss
Sass本身是对CSS的语法增强,它有两种语法,现在使用更多的是SCSS。所以你会发现,在安装和配置loader时都是sass-loader,而实际的文件后缀是.scss。sass-loader可以将SCSS语法编译为CSS,因此在使用时通常还要搭配css-loader和style-loader。
安装
npm install sass-loader node-sass
loader本身只是编译核心库与Webpack的连接器,因此这里我们除了sass-loader以外还要安装node-sass,node-sass是真正用来编译SCSS的,而sass-loader只是起到黏合的作用
实例
//新建一个style.scss
$primary-color:#09c;
div{color:$primary-color}
//webpack.config.js
module.exports = {
...
module: {
rules: [{
test: /.scss$/,
//通过将 style-loader 和 css-loader 与 sass-loader 链式调用,可以立刻将样式作用在 DOM 元素。
use: [{
loader: "style-loader" // 将 JS 字符串生成为 style 节点
}, {
loader: "css-loader" // 将 CSS 转化成 CommonJS 模块
}, {
loader: "sass-loader" // 将 Sass 编译成 CSS
}]
}]
}
};
//main.js
import './style.scss';
function Component(){
var div=document.createElement('div')
div.innerHTML="初始化一个项目"
return div
}
document.body.appendChild(Component())
打包后就能看到样式呈现在页面上了
less
Less同样是对CSS的一种扩展,安装loader和其本身的编译模块,配置与SCSS相似。
npm install --save-dev less-loader less