webpack常见应用

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,发现浏览器控制台报错并且指示了错误的位置

image.png

这时候把错误改回来,发现没有报错且正确输出了

image.png

代码分离

代码分离可以用于获取更小的 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

image.png

自动编译

每次要编译代码时,手动运行 npm run build 就会变得很麻烦

webpack 中有几个不同的选项,可以帮助你在代码发生变化后自动编译代码:

  1. webpack's Watch Mode
  2. webpack-dev-server
  3. 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 服务器就会自动重新加载编译后的代码并呈现新的页面。

如果误关了浏览器,可以随时在终端窗口找到本地链接进行访问

image.png

不过在开启Web服务器之前,需要在html-webpack-plugin插件的基础上npm run build自动生成一个index.html,否则启动服务器会看不要预期的页面。这是因为配置上写的是从dist里访问文件,如果dist里面没有该文件自然访问不到了。当然如果本身dist里面就有html,就不需要再build了。

处理样式

分离样式文件

一般来说,在生产环境下,我们希望样式存在于CSS文件中而不是style标签中,因为文件更有利于客户端进行缓存。抽取出来后样式表将不再依赖于 JavaScript。Webpack社区有专门的插件专门用于提取样式到CSS文件的:

  1. extract-text-webpack-plugin(适用于Webpack 4之前版本)
  2. 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。

image.png

样式的提取是以资源入口开始的整个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
posted @ 2020-09-01 15:12  sanhuamao  阅读(277)  评论(0编辑  收藏  举报