2020年,《深刻浅出Webpack》(吴浩麟2018/01)学习总结

前言

2020年1月18号,还有一周就是农历2020年的春节了,我提早请了6天的假,回家过年。此时公司的项目仍是如火如茶的开展,一如既往的赶工。css

原本打算年前辞去工做,回家过个长春节,来年金三银四江湖再会。(毕竟,这是我二十多年来,第一次回老家过年)html

待遇通常,配的也是租来的黑瞎眼的古董thinkPad T430笔记本,每天无条件加班9->0点。要是我辞,试用期内,不辞,过完年就过试用期了,考虑到新项目尚未作完(期实也就是作了一个月,可是已完成7成了),负责任的我犹豫了好久,没有提交那份书。前端

拿了在这里上班的第一个月工资,以及卖掉了本身的游戏本,换了一个二手的macbook pro。vue

刚入行前端的头一年,我知道,我要的是知识,我要的不是没日没夜的加班,还有不停的百度,不停的试完一个博客的案例发现不合适又找下一个。node

应了当前项目两个开发环境,三个打包路径改来改去的痛点,我决定在这个春节,怎么也要抽点时间出来看完这本《深刻浅出Webpack》。webpack

看的是电子书,2018年1月发售的,在京东上找,这本书还在买。看了京东对本书的简介好像并无更新。书中用的webpack 是@2版并穿插@3版本。据说webpack 4有了相对大的更新,目前好像更新到了5,别说老油条,我一个新人,都以为前端学起来费劲。web

截屏2020-02-03下午10.09.27.png

对于书上的安装方法来装各个工具是版本是不对的。可是能不能用,出现的坑,我都在下文的总结中列出来吧。vue-cli

本次学习没有过深研究webpack,参照了vue-cli2.9版本搭建的webpack模版,以及webpack 4.4的官方中文文档(不知道怎么能看到旧文档),对于要在vue项目中用到的一些配置做了学习。npm

后期跟据须要会不断的完善这份总结。json

有不少过来人都说前端更新快,看书学习不是最佳方法(考虑到书的价格不低),可是我仍是比较喜欢看书,本身也买了不少书,这本是到目前为止看的惟一一本电子书。这本书到底值不值看?

前半部分对api的介绍没有webpack官方文档好理解,可是后半段对webpack的配置优化总结及一些按例仍是很值得新手去看

DevServer

文中没有很明确说到如何启动build和运行webpack中的命令,

期实,运行webpack就是在终端中(进入当前文件夹)输入webpack,回车后项目就打包放在dist文件夹了,可是,这时打包的结果是一个js文件,入口index.html文件仍是在dist同级目录下的那个index.html。

当你的webpack没有全局安装时,不能直接在终端中输入webpack,而是要输入webpack所在的文件,在node_modules/.bin/webpack。直接输入

node_modules/.bin/webpack

回车。

运行devServer时也是在这个目录下

node_modules/.bin/webpack-dev-server

要看到热更新,还要改一下入口文件index.html中的bundle.js的路径,由于devserver不会理会webpack.config.js里的output.path属性。

<script src="./dist/bundle.js" ></script>
<!-- 改成下面的--!>
<script src="bundle.js"></script>

固然这些命令是能够写在package.json文件里的script下,而后经过npm run 去运行的

1EkUFs.md.png

Entry

1. context(webpack默认的打包相对路径)

更改:在webpack的配置文件中:

const    path = require('path');
{
    context: path.resolve(__dirname,'app'),//或者 ./ ../ 等
}

2. 入口文件

entry: {
    app: './src/main.js',//能够配置多个入口,或动态入口
}

3. output

output: {
    filename: '[name].js',//[name]是node内置的name变量
    path: path.resolve(__dirname, '../dist'),//必须是绝对路径,经过之path能够找出绝对路径。
    publicPath: '',
}

说明:

filename 输出文件的名称

path 输出文件存放在本地的目录

publicPath 异步加载的地址,(发布到线上资源的URL前缀)

4. resolve

配置模块如何解析,

alias

改import后面的引用路径,从而达到简写

resolve: {
    alias: {
        "@": resolve('src'),//resolve方法是找到src是绝对地址
        "vue$": './src/vue/'
    }
}
//当引用
import Comp from 'vue$/vue';
import Button from '@/components/button';
//实际会被改为
import Comp from './src/vue/vue';
import Button from './src/components/button';

extensions

使import 的引用路径不用写相应的后缀名,

resolve: {
    extensions: ['.js','.json'],//默认值
    //extensions: ['.js','.vue','.json'],vue项目能够加入'.vue'
}

5. devServer

用于描述web pack-dev-server的行为选项

hot

模块热替换采用不刷新整个页面,而是热替换有变动的模块来更新浏览器视图,默认是刷新整个页面

devServer: {
    hot: true,
}

historyApiFallback

用于方便开发使用了HTML5 History API的单页面应用

当设为:

devServer: {
    historyApiFallback: true,
}

任意的 404 响应均可能须要被替代为 index.html,但只能应用于只有一个html文件的应用。

若是要devServer能跟据不一样的页面请求后回不周的html文件,配置:

historyApiFallback: {
  rewrites: [
    // /user开头的都返回user.html
    { from: /^\/user/, to: '/user.html'},
    { from: /^\/game/, to: './game.html'},
    //其余的返回index.html
    { from: /./, to: '/index.html'}
  ]
}

compress

host

port

open

boolean,在devServer启动且第一次构建完成时,自动打开系统默认浏览器

proxy

使用了http-proxy-middleware包,用于代理url。

直接代理:

devServer: {
    proxy: {
        "/api": "http://localhost:3000",
    }
}

当请求/api/index时会被代理到 'http://localhost:3000/api/index'

若是你不想始终传递 /api ,则须要重写路径:

proxy: {
    "/api": {
        target: "http://localhost:3000",
        pathRewrite: {
            "^/api": "",
        }
    }
}

若是是https请求加入source: false,

proxy: {
    source: false,//source直译:安全的
}

解决跨域:changeOrigin

proxy: {
    changeOrigin: true,
}

本地就会虚拟一个服务器接收你的请求并代你发送该请求

quiet

boolean

启用 quiet 后,除了初始启动信息以外的任何内容都不会被打印到控制台。这也意味着来自 webpack 的错误或警告在控制台不可见。

webpack的其余零散配置

1. target

构建针对不一样运行环境的代码

2. devtool

配置如何生成source Map,以方便调试

string boolean

默认: false

不一样的值会明显影响到构建(build)和从新构建(rebuild)的速度。

vue-cli2中应在development开发环境的devtool为:cheap-module-eval-source-map

对于适合开发环境的值,webpack文档中有以下说明:

eval - 每一个模块都使用 eval() 执行,而且都有 //@ sourceURL。此选项会很是快地构建。主要缺点是,因为会映射到转换后的代码,而不是映射到原始代码(没有从 loader 中获取 source map),因此不能正确的显示行数。

eval-source-map - 每一个模块使用 eval() 执行,而且 source map 转换为 DataUrl 后添加到 eval() 中。初始化 source map 时比较慢,可是会在从新构建时提供比较快的速度,而且生成实际的文件。行数可以正确映射,由于会映射到原始代码中。它会生成用于开发环境的最佳品质的 source map。

cheap-eval-source-map - 相似 eval-source-map,每一个模块使用 eval() 执行。这是 "cheap(低开销)" 的 source map,由于它没有生成列映射(column mapping),只是映射行数。它会忽略源自 loader 的 source map,而且仅显示转译后的代码,就像 eval devtool。

cheap-module-eval-source-map - 相似 cheap-eval-source-map,而且,在这种状况下,源自 loader 的 source map 会获得更好的处理结果。然而,loader source map 会被简化为每行一个映射(mapping)。

Vue-cli2在build生产环境中的devtool为: #source-map

不知道为何加了一个'#'

对于适合生产环境的值,webpack文档中有以下说明:

(none)(省略 devtool 选项) - 不生成 source map。这是一个不错的选择。

source-map - 整个 source map 做为一个单独的文件生成。它为 bundle 添加了一个引用注释,以便开发工具知道在哪里能够找到它。

你应该将你的服务器配置为,不容许普通用户访问 source map 文件!

hidden-source-map - 与 source-map 相同,但不会为 bundle 添加引用注释。若是你只想 source map 映射那些源自错误报告的错误堆栈跟踪信息,但不想为浏览器开发工具暴露你的 source map,这个选项会颇有用。

你不该将 source map 文件部署到 web 服务器。而是只将其用于错误报告工具。

nosources-source-map - 建立的 source map 不包含 sourcesContent(源代码内容)。它能够用来映射客户端上的堆栈跟踪,而无须暴露全部的源代码。你能够将 source map 文件部署到 web 服务器。

这仍然会暴露反编译后的文件名和结构,但它不会暴露原始代码。

在使用 uglifyjs-webpack-plugin 时,你必须提供 sourceMap:true 选项来启用 source map 支持。

其中,devtool有六个值,这六个值能够随意组合:

  1. eval: 用eval语句包裹须要安装的模块。
  2. source-map: 生成独立的source map文件
  3. hidden: 不在js文件中指出source map文件所在,这样浏览器就不会自动加载source map.
  4. inline: 将生成的source map转换成base64格式内嵌在js文件中。
  5. cheap: 在生成的source map中不会包含列信息,这样计算量更小,输出的source map文件更小;同时 loader输出的 source map不会被采用。
  6. module: 来自loader的 source map被简单处理成每一行一个模块。

3. watch和watchOptions

watch

webpack的监听模式,它支持监听文件更新,在文件发生变化时从新编译。

默认为false

在webpack-dev-server 和 web pack-dev-middleware中是默认开启的。

watchOption是相应的配置

npm script

也就是webpack的命令,写在package.json的script字段里

代码检查

经常使用工具: ESlint、TSlint、stylelint

价绍了ESlint的一些设定,TSlint用于TypeScript,stylelint用于css

file-loader与url-loader

  1. File-loader

    改变打包后的文件名,以方便寻找路径,用hash命名。

  2. Url-loader

    将小文件的资源改成base64格式以嵌入代码中。

    好处:http/1协议中,每加载一次资源都要创建一次http请求,将小图片注入代码中能够减小这一次请求

    很差处: 会导至js/css代码体积变大,文件过大将使网页加载缓慢。

    module.export = {
        module: {
            rules: [
                {
                    test: /\.png$/,
                    use: [
                        {
                            loader: 'url-loader',
                            options: {
                                //30KB如下的文件采用url-loader,
                                limit: 1024*03,
                                //不然用file-loader,
                                fallback: 'file-loader',
                            }
                        }
                    ]
                }
            ]
        }
    }

webpack优化

踩坑1: 更改paralleUglifyPlugin并无加快打包的速度

个人项目是用vue-cli2拉的默认环境,开发了一段时间,也加入了好多第三方包。平时的打包大概是50秒,改为paralleUglifyPlugin后,时间为48.5秒。

其中,配置时也有不少报错:正确的配置:

new ParallelUglifyJsPlugin({
    //uglifyJs要改成uglifyES(求上传服务器验证)
  uglifyES: {
    output: {
      beautify: false,
      comments: false,
      }
  },
  compress: {
      warnings: false,
    drop_console: true,
    collapse_vars: true,
    reduce_vars: true,
  },
  sourceMap: config.build.productionSourceMap,//false
  parallel: true,
}),

区分环境

书中介绍的方法是设置process.env.NODE_ENV

const DefinePlugin = require('webpack/lib/DefinePlugin');

module.export = {
    plugins: [
        new DefinePlugin({
            'process.env': {
                NODE_ENV: JSON.stringify('production')
            }
        })
    ]
}
在定义环境时用JSON.stringify的缘由是,环境烃量的值须要是一个由双引号包裹的字符串,而JSON.stringify('production')的值正好等于'"production"'
相关文章
相关标签/搜索