3

前言

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

项目太赶了,项目经理给了个模版这开发在里面开发,其间也没有什么时间增值学习。

公司配的联想t430笔记本屏幕没法看。自己拿了在这里上班的第一个月工资,以及卖掉了自己的游戏本,换了一个二手的macbook pro。

咬牙坚持了下来。

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

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

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

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

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

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

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

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

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

开始吧!让我们学习进步起来!
截屏2020-01-19下午10.51.58.png

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"'

maYunLaoXi
65 声望3 粉丝

前端开发工程师,自由摄影师