webpack基础配置

232 阅读10分钟
区别 webpack1.x.x webpack3.x.x
webpack.config.js 的 output-path 直接写文件路径'./dist/js' 要用到 node.js 的 path 对路径进行转换

准备工作 💬

安装webpack

mkdir webpack-demo
cd webpack-demo
npm init
touch hello.js world.js style.css
npm install webpack@3.11.0 -D

因为是局部安装,所以每次运行webpack的时候,要在终端输入./node_moduls/.bin/webpack,比较麻烦,所以我们结合npm的script简化一下操作,

module.exports={
  ...
  "scripts": {
    "test""echo \"Error: no test specified\" && exit 1",
    "webpack""./node_modules/.bin/webpack"
  }
}

之后就只要每次打包就只要运行 npm run webpack就OK了,运行webpack时可以带上一些好用的参数,比如--watch, 之后文件改变时便会自动打包

但是当我运行打包命令时,报错了, 报错原因是:

RROR in ./style.css
Module parse failed: Unexpected token (1:9)
You may need an appropriate loader to handle this file type.

由此可见,webpack不接受.css 的文件类型,所以我们需要引入css-loaderstyle-loader来解析样式文件

安装css-loader和style-loader

  1. npm install css-loader@3.3.0 style-loader@1.2.1 -D

  2. 绑定 loader:

    1. require的时候写成:require('style-loader!css-loader!./style.css'),注意必须style-loader在前,css-loader在后
    2. 命令行绑定webpack hello.js hello.bundle.js --module-bind "css=style-loader!css-loader",注意gitbash 要用单引号才行,用系统的cmd命令要用双引号
  3. style-loader的作用是将css-loader解析好的css代码加一个style标签插入html文件中

遇到的问题:

一些命令:

npm view css-loader version 查看版本

npm install --save-dev pkg@1.2.1 安装特定版本依赖包

npm uninstall pkg 卸载依赖包

npm install -D 即 npm install module_name --save-dev 了解 npm install -S -D 的区别,看这篇就完事了

2 webpack基本配置

💎我这里安装的是webpack 3.x.x,配置过程中发现不同版本的webpack配置方式区别挺大的...

2-1建立项目的webpak配置文件

webpack --config config_filename 指定使用特定的配置文件进行webpack打包,比如开发环境、生产环境各自的打包配置文件。

2-2webpack配置的entry和outpath

  • entry参数

entry可以有三种类型:

1.一个字符串

所有的依赖都在一个入口文件中指定(即在这一个文件中require所有的依赖)

2.一个数组

解决两个或多个互不依赖的文件打包在一起的问题

3.一个对象

  entry: {
    home: './home.js',
    about: ['./about.js','./contact.js']
  }

key为chunk name,value既可以是单个文件名,也可以是一个包含多个文件路径的数组

  • output参数

单个入口:

  entry:['./src/script/a.js','./src/script/main.js'], 
  output:{
      path:path.resolve(__dirname, './dist/js'),
      filename:'bundle.js'
  }

多个入口(entry为一个对象的时候):

如果配置创建了多个单独的 "chunk"(例如,使用多个入口起点或使用像 CommonsChunkPlugin 这样的插件),则应该使用占位符(substitutions)来确保每个文件具有唯一的名称。

  entry:{
      a:'./src/script/a.js',
      main:'./src/script/main.js'
  },
  output:{
      path:path.resolve(__dirname, './dist/js'),
      filename:'[name]-[hash].js' // hash为本次打包的hash值
  }

filename还可以写成filename:'[name]-[chunkhash].js',文件改变,这个值就会变;文件不变,这个hash值就不变。可以看做文件的版本号。打包之后可以看到dist目录下会多出了两个js文件,分别由a.js和main.js打包而来。

插件

  • html-webpack-plugin

作用:打包后的文件名是动态的,html-webpack-plugin可以实时更新html文件对打包后的js文件名的引用

安装:npm install html-webpack-plugin -D

使用:1.在webpack.config.js中引用插件 2.增加plugins参数,生成一个对象 3.可以给plugin构造函数传参以配置插件

var path = require('path');
var htmlWebpackPlugin= require('html-webpack-plugin')
module.exports = {
   //context,          // 整个运行环境的上下文,默认值为运行该脚本的目录
    entry:{            //打包入口
        a:'./src/script/a.js',
        main:'./src/script/main.js'
    }, 
    output:{
        path:path.resolve(__dirname, './dist'),
        filename:'js/[name]-[chunkhash].js',
        publicPath:'http://cdn.com/'   //当正式上线的时候需要用到;比如正式环境的代码是存放在http://cdn.com/上,那么在index.html中引用的js src需要加上这个publicPath
    },
    plugins:[
        new htmlWebpackPlugin({
            template:'index.html',           //根目录的index.html
            filename:'index-[hash].html',   // 可以指定生成的文件名,hash为index.html的md5值
            // inject:'head',               //js放在head标签中
            title:'Hello webpack',          //自定义参数
            date:new Date(),                //自定义参数
            minify:{                        // 压缩html的配置
                removeCommentstrue//删除注释
                collapseWhitespace:true // 删除空格
            }
        })
    ]
}

运行npm run webpack,会发现dist/js下多出了一个index-[hash].html的文件,

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>webpack demo</title>
</head>
<body>
    <script type="text/javascript" src="main-f379fa9adbfc62591409.js"></script><script type="text/javascript" src="a-b4a524f95bfe8e75f7a3.js"></script></body>
</html>

上面的操作只生成了一个html,那当我们需要生成多页面应用(即需要生成不止一个html文件)时,要怎么实现呢?很简单,只要再new一个htmlWebpackPlugin对象,放到plugins数组里就可以了!

    plugins:[
        new htmlWebpackPlugin({
            template:'index.html',  
            filename:'a.html',     
            inject:'body',          //js放在body标签中
            title:'Hello a',
            chunks:['main','a']     //允许该html里只加载某些特定的chunk;表示包含main chunk和a chunk
        }),
        new htmlWebpackPlugin({
            template:'index.html'            filename:'b.html'            inject:'body',
            title:'Hello b',
            chunks:['main','b']            //b chunk
        }),
        new htmlWebpackPlugin({
            template:'index.html'            filename:'c.html'            inject:'body',
            title:'Hello c',
            chunks:['main','c']            // c chunk
        })
    ]

优化点

上面的js都是通过script src插入到html页面中的,如果可以将脚本以内联脚本的格式插入到页面中,会大大减少http请求的数量,加快脚本的加载速度。

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title> <%= htmlWebpackPlugin.options.title %></title>
    <script type="text/javascript">
        <%= compilation.assets[htmlWebpackPlugin.files.chunks.main.entry.substr(htmlWebpackPlugin.files.publicPath.length)].source() %>
    </script>
</head>
<body>
    <% for(var key in htmlWebpackPlugin.files.chunks){ %>
        <% if(k !== 'main') { %>
            <script src=" <%= htmlWebpackPlugin.files.chunks[k].entry %>"></script>
        <% } %>
    <% } %>

    <!-- 我是一行注释 -->
</body>
</html>

这时候还要将插件配置中的inject参数设为false

html-webpack-plugin的更多配置可参考html-webpack-plugin文档

处理项目中的资源文件

4-1什么是Loadr以及Loader的特性

  • loader的作用:用来处理一些资源文件

  • loader可以通过npm安装

  • 使用loader的三种方式:

    • 通过在require文件的时候指定处理文件的loader: require("loadername!./file.txt)

    • 通过配置:

      rules是一个数组,数组中的每一项的test表示匹配文件名的正则,匹配到了就用use指定的loader去处理

    module.exports = {
     module: {
       rules: [
         { test/\.css$/use'css-loader' },
         { test/\.ts$/use'ts-loader' }
       ]
     }
    };
    
    • 通过CLI:

      webpack hello.js hello.bundle.js --module-bind "css=styl e-loader!css-loader"

4-2 使用babel-loader转换ES6代码

4-3 处理项目中的css

4-4 使用less和sass

4-5 处理模板文件

4-6处理图片以及其他文件:file-loader

在模板中引用图片的相对路径,不会被替换成打包后的图片路径。解决方法有:1.模板中的图片尽量通过cdn,即绝对路径引用。2. 模板中引用相对路径的图片时,引用方法为:

    <img src="${require('../../assets/20200921_1025105332770146.png')}" >

url-loader 可以配置一个limit参数,当图片大小小于这个参数时,这个图片会被转成base64插入到图片地址中。而非原来的http请求 第一个截图为用file-loader打包的打包情况:

第二张截图为用url-loader打包的情况(图片文件没有被打包进来,但打包后的bundle文件变大了):

参考资料:

Webpack Plugin的配置-官网:v4.webpack.js.org/configurati…

wepack 配置参考:

https://www.jianshu.com/p/b41dc1e1d4c0

https://www.jianshu.com/p/a184afaa0cce

https://blog.csdn.net/weixin_30897079/article/details/97591873