webpack4学习之路

1.webpack的用处

1.1 打包 把多个文件打包成一个文件,减少服务器压力

1.2 转化 less/stylus/sass 需要loader进行转化

1.3 优化

2.webpack配置文件webpack.config.js

2 入口出口

2.1 最简单的配置文件,只包含入口和出口, 注意output里面的path要用绝对路径,不然会报错。

wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==

2.2 如果就这么运行的话,会发现webpack出来并没有出现dist这个文件,这是output的path里面书写错误。不是./dist 也不是 .dist,而是/dist

path: __dirname + '/dist',

wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==

2.3 入口input的除了这种对象的写法,还可以这么写,这个只能用于只有一个入口文件的时候

entry: './path/to/my/entry/file.js'

wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==

2.4 webpack配置文件并不是一定要叫webpack.config.js,只是默认情况下,会自动搜索当前目录的 webpack.config.js 

我把配置文件的名字修改之后再进行打包,仍然能打包,只不过名字变成了main.js,这是由于在package.json文件的main属性中指定了加载的入口文件。这在之前webpack3里面是会报错的。

package.json中main属性指定了程序的主入口文件。意思是,如果你的模块被命名为foo,用户安装了这个模块并通过require("foo")来使用这个模块,那么require返回的内容就是main属性指定的文件中 module.exports指向的对象。
它应该指向模块根目录下的一个文件。对大对数模块而言,这个属性更多的是让模块有一个主入口文件,然而很多模块并不写这个属性。

如果非要使用自己定义的webpack配置文件也是可以的 webpack --config xxx.config.js 即可。

wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==

2.5 npm 的 scripts功能

npm 允许在package.json文件里面,使用scripts字段定义脚本命令。当你执行npm xxx的时候,它会自动找到package.json里面的scripts属性里所对应的键值,并执行它。

如下所示,在scripts里面又这样一个键值对 test : webpack,当我们在命令行里面输入npm run test的时候,其实真正执行的是webpack。

wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==

 

2.6 多入口单出口

如果是多入口但是还是想打包成一个文件,那么不能像下面这样写,这样表示的是希望打包成多个不同的文件,但是出口却只有一个bundle.js所以发生冲突。

module.exports = {
    entry: {
        index: './src/index.js',
        sally: './src/sally.js'
    },
    output: {
        path: __dirname + '/dist',
        filename: 'bundle.js'
    }
}/*  */

wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==

wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==

修改如下

module.exports = {
    entry: {
        index: ['./src/index.js', './src/sally.js']
    },
    output: {
        path: __dirname + '/dist',
        filename: 'bundle.js'
    }
}/*  */

wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==

这样index.js文件和sally.js文件就能打包到同一个文件里,并且执行顺序是按照引入顺序来的。

2.7 多入口多出口

[name].js 表示文件名是一个变量 由打包时候本身的文件名决定。

module.exports = {
    entry: {
        index: './src/index.js',
        sally: './src/sally.js'
    },
    output: {
        path: __dirname + '/dist',
        filename: '[name].js'
    }
}/*  */

wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==

可以看到,打包后的文件名字和入口文件一致

wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==

 

3 生产模式/开发模式

之前我们一致能看到一段warning,他的意思是我们打包时候没有设置是生产环境还是开发环境,默认情况会使用开发环境

WARNING in configuration
The 'mode' option has not been set, webpack will fallback to 'production' for this value. Set 'mode' option to 'development' or 'production' to enable defaults for each environment.
You can also set it to 'none' to disable any default behavior. Learn more: https://webpack.js.org/concepts/mode/

用开发模式和生产模式分别打个包,前者的size是3.84kb,后者是980bytes,明显小很多,这说明了webpack自动在生产模式的时候为我们进行了优化压缩。

wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==

 

4 plugin---html-webpack-plugins

4. 1生成单页面

The plugin will generate an HTML5 file for you that includes all your webpack bundles in the body using script tags. 

之前我们使用打包好的bundle.js都是我们手动创建了一个页面,手动的引入bundle.js这个文件。而html-webpack-plugins会自动形成一个html文件并引入打包好的js文件。

下载好插件并在webpack配置文件顶部引入该插件(webpack没有自带这种功能,所以插件都是需要自己引入的)

const HtmlWebpackPlugin = require('html-webpack-plugin');

wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==

写好配置文件 重新打包会发现dist里面多了一个index.html文件,这个就是插件生成的。打开之后发现它自动的把我们的打包js文件index.js和sally.js添加了进去。

wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==

 plugins: [
        new HtmlWebpackPlugin({
            template: './src/template.html',//生成的html文档使用此模版
            hash: true,//给每个注入的文件带上一个独一的hash码,防止缓存
            minify: {
                collapseWhitespace: true,//压缩 折叠空白区域
            },
            title: 'hi there~',//给模版添加title 在模版内需要用特殊的语法
        })
      ]

wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==

<title><%= htmlWebpackPlugin.options.title%></title>

wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==

4.2 生成多页面

生成多页面只需要多new一次就可以了,但是一定记得要写上filename,不然还是只会生成一个。

chunks属性用于指名引入哪一个打包文件,如果没有这个属性,默认引入全部。

    plugins: [
        new HtmlWebpackPlugin({
            filename: 'index.html',
            template: './src/template.html',
            hash: true,
            minify: {
                collapseWhitespace: true,
            },
            title: 'hi there~',
            chunks: ['index']
        }),
        new HtmlWebpackPlugin({
            filename: 'sally.html',
            template: './src/template.html',
            hash: true,
            minify: {
                collapseWhitespace: true,
            },
            title: 'hi there~',
            chunks: ['sally']
        })
      ]

wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==

sally.html只引入了sally.js这个打包文件。

wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==

5 plugin---clean-webpack-plugins

每次打包都要先把之前的dist文件删除,很麻烦,这个插件的功能就是让我们每次打包之前清除之前的打包文件。

const CleanWebpackPlugin = require('clean-webpack-plugin');

wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==

新版的cleanwebpackplugin不再接收数组为参数,指接收一个对象作为option,并且会默认找到你的打包文件自动清除,所以在不需要特殊需求情况下直接在plugin里面new一下就好了。

wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==

wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==

6 css-loader/style-loader

现在我们改变一下文件的结构,如下所示增加了一个css文件。

 wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==

然后我们在index.js里面引入这个css文件。

之前我我对webpack里面js引入css一直有一些疑问

1.为什么我们要在js文件里面引入css文件?

Answer:因为webpack的原理是从一个入口文件开始寻找这个文件的依赖,所以如果我们想要吧css打包进去,就必须把css文件引入入口js文件里面。也就是css-loader对css文件进行加载,然后style-loader把css文件添加的html文件的<style></style>标签里面~

2.不能在html里面引入吗??

Answer:也不是不可以,但是我们这里用了html-webpack-plugin,这个html是动态生成的,如果我们写到html里面那么我们该如何对应html文件和它的css文件呢?

3.而且js里面可以引入css文件?具体怎么引入?

Answer:可以引入,用commonjs或者es6的标准都可以。

wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==

4. 文件没有export就能import吗?import的时候不需要取名字吗例如import xxx from xxx?

接着我们开始打包,发现报错了。说明webpack是不能处理css文件的,需要一个合适的loader来处理这类型的文件。

wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==

css文件类型需要css-loader和style-loader,下载好之后需要在webpack配置文件里面进行如下配置,之后npm run dev就没问题~!

注意一点,css-loader必须写在style-loader之前,地理位置之后,因为webpack是先用css-loader对文件进行加载,再用style-loader把样式插入的style里面。这样也解释了之前的问题1,我们在js文件里面引入css文件,是怎么作用到html文件里面的。具体来说,就是css-loader对css文件进行加载,然后style-loader把css文件添加的html文件的<style></style>标签里面~

module.exports = {
  module: {
    rules: [
      {
        test: /\.css$/,
        use: ['style-loader', 'css-loader'],
      },
    ],
  },
};

wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==

wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==

 

7.url-loader/file-loader

7.1 图片加载需要loader

如果引入下载下来的图片,报错如下。需要下载一个url-loader 和 file-loader。

background-image: url('./index.jpg');

wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==

Uncaught Error: Module parse failed: Unexpected character '�' (1:0) You may need an appropriate loader to handle this file type.
(Source code omitted for this binary file)

url-loader配置如下:

{
        test: /\.(png|jpg|gif)$/i,
        use: [
          {
            loader: 'url-loader',
            options: {
              limit: 8192
            }
          }
        ]
      }

wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==

7.2 url-loader依赖file-loader

Uncaught Error: Module build failed (from ./node_modules/url-loader/dist/cjs.js):
Error: Cannot find module 'file-loader'

但是还是报错,这是因为url-loader是依赖与file-loader的,一般来说url-loader是包含file-loader的不必两个都下载,但是防止出错,还是都下载了把。

成功~

wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==

而且图片的地址还经过了hash化~

wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==

7.3 一些问题

那么问题来了

1.为什么图片需要一个特殊的loader呢?

Anwser:webpack最终会将各个模块打包成一个文件,因此我们样式中的url路径是相对入口html页面的,而不是相对于原始css文件所在的路径的。这就会导致图片引入失败。这个问题是用file-loader解决的,file-loader可以解析项目中的url引入(不仅限于css),根据我们的配置,将图片拷贝到相应的路径,再根据我们的配置,修改打包后文件引用路径,使之指向正确的文件。

2.配置里面有个options的limit属性,是做什么用的呢?

Answer:如果图片较多,会发很多http请求,会降低页面性能。这个问题可以通过url-loader解决。url-loader会将引入的图片编码,生成dataURl。相当于把图片数据翻译成一串字符。再把这串字符打包到文件中,最终只需要引入这个文件就能访问图片了而不需要file-loader修改路径了,这样减少了一次请求!而加快了页面的加载。当然,如果图片较大,编码会消耗性能。因此url-loader提供了一个limit参数,小于limit字节的文件会被转为DataURl,大于limit的还会使用file-loader进行copy。

所以,图片小于限制的时候用 url-loader,其他情况都用 file-loaderurl-loader应该是file-loader上加了一层过滤。

3.既然url-loader和file-loader主要解决的是一个路径问题,那么我不用相对路径,而用网上的图片地址这样的绝对路径,是不是可以解决这个问题呢?

Answer:是的,可以的!之前在下载这两个loader之前,我用的是图片的网络地址,这样并不会报错。

4.如果图片是本地图片(已经下载好的图片并已经放在项目内部了),那么本身也不需要http请求图片了,那么这个时候url-loader还有用处吗?还是说本地图片统一用file-loader,url-loader则用于非本地图片?

Answer:首先这个问题就是错误的,只要是页面访问图片都需要请求!因为图片不会预先加载到浏览器,所以就请求一次!!这个时候,你的浏览器是客户端,你的电脑是一个服务器,浏览器就会向这个本地服务器发送请求,加载图片。如果采用url-loader,在不超过limit的情况下webpack的loader直接把图片打包为base64编码的代码放在文件直接在js文件里,就不用请求图片了!! 并且,因为url-loader是直接把图片的编码放在js文件里面,所以也不存在路径问题了,下图为采用图片不超过limit大小的时候,打包出来的文件,可以看到是没有图片文件的~

 

但是如果图片超过了limit,webpack打包就会很慢得不偿失,所以limit以上的图片就会采用http请求方式来获取图片,这个时候用的就是file-loader了,可以从下面的图片看到打包后的文件有图片

wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==

7.4 在js里面加载图片

webpack处理js文件不需要loader,那么我们在js里面添加处理图片是不是不需要loader呢?

为了验证想法,index.js里面修改如下

import imgsrc from './index.jpg';
const temp = document.getElementById('app');

let oimg = new Image();
oimg.onload = function () {
    temp.getElementById('app').appendChild(oimg);
}
oimg.src = imgsrc;

wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==

证明这是可以的~

wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==

 

7.5 outputpath

如果想要把图片打包到单独的文件夹里面,可以在outputpath这个属性里面设置

 

8 extract-text-webpack-plugin

8.1

It moves all the required *.css modules in entry chunks into a separate CSS file. So your styles are no longer inlined into the JS bundle, but in a separate CSS file (styles.css). If your total stylesheet volume is big, it will be faster because the CSS bundle is loaded in parallel to the JS bundle.

这段话取自npm,他的意思是extract-text-webpack-plugin这个插件可以帮我们吧css文件单独打包到一个css文件夹里面,这样css不再像以前那样放在打包的js文件里面了。特别是如果你的css文件特别长,这样有助于提升打包速度,因为js文件和css文件打包是可以并行的。

插件配置如下

const ExtractTextPlugin = require("extract-text-webpack-plugin");
 
module.exports = {
  module: {
    rules: [
      {
        test: /\.css$/,
        use: ExtractTextPlugin.extract({
          fallback: "style-loader",
          use: "css-loader"
        })
      }
    ]
  },
  plugins: [
    new ExtractTextPlugin("css/index.css"),
  ]
}

wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==

引入插件和注册插件这两步和其他的别无二致,但是为什么这个插件还要修改loader的配置呢?

Answer:css-loader是起着编译的作用,style-loader是吧编译后的css插入html文档里面的style标签内。现在我们通过extract-text-webpack-plugin插件吧css文件单独打包到别的位置,然后html文档则会通过引入的方式来获取css,这样style-loader也就不再需要了,所以我们把style-loader放在fallback里面,表示我们不用extract-text-webpack-plugin提取css的时候,才使用style-loader。而外面包裹的那层ExtractTextPlugin.extract,以我的理解,是用来专门单独打包css的。

8.2 webpack4 和 npminstall extract-text-webpack-plugin@next

现在npm 上只写了与webpack 1,2,3兼容的extract-text-webpack-plugin的版本,如果我们按正常的流程下载打包则会报错,因为webpack4 配合的是extract-text-webpack-plugin": "^4.0.0-beta.0 这个版本,正确的命令是:

npm install extract-text-webpack-plugin"@next -D

wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==

8.3 publicPath

等新版本插件下载好之后打包果然没问题了,打包后文件如下,因为我们在注册的时候写的是css/index.js 所以打包后会有一个新的文件夹css 里面的有css文件index.css

wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==

然后你以为这么简单就结束了吗?naive!我们打开页面一看又有新的报错!什么意思,图片文件的路径不对,我们找不到。

wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==

看下实际的路径是这样的,在css文件里面我们取图片用的是./images/index.jpg,但是打包的时候,我们的图片却是单张被打包到css文件夹外的(图片超过了limit大小,使用file-loader),这就导致路径不对,所以出错。

wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==

那么问题又来了

为什么之前没有用extract-text-webpack-plugin插件的时候,也是一样的文件结构却没有出错呢?而且我们不是没有file-loader,这个loader吃白饭的?

Answer:首先我们要明白之前我们之所以能够在html文件里面正确引入css文件中的图片,是因为我们把css打包进了js文件中,然后file-loader才找到图片,然后在html文件里面插入正确的路径。现在我们用了extract-text-webpack-plugin之后我们把css单独打包进了一个css文件夹内,js文件里面不再有css包括其图片内容,所以file-loader也不再起作用了。

可以看到当我们不使用提取css插件的时候,js文件里面是有css的内容的,而使用插件之后js里面则不再有css内容

wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==

解决办法:ExtractTextPlugin里面有个publicpath的属性就是用来解决这个问题的,只需要我们在这个属性里面填写相对路径的位置,那么我们的图片都会在这之前添加这个相对路径,例如publicpath:‘../‘,那么我们得到下面的路径,前面添加了../。

wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==

 

9 sass-loader/node-sass

使用sass预处理器,之前的template模版修改如下,id为app的dom由css修饰,id为sass的dom由sass修饰

<body>
    <div id="app">
        hello i am sally!
    </div>
    <div id="sass">
        i am sass
    </div>
</body>

wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==

需要的sass语法如下

$index: #F90;
#sass{
    color: $index;
}

wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==

webpack配置如下:

wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==

在使用sass的语法过程中我有很多的问题,如下:

1 sass应该单独成文件吗?还是写在css里面?

Answer:

1.1 应该单独成文件,下面的图片我们可以看到编译器会提醒语法错误,而且如果要用sass的话,一般来说就不会再使用css了。

wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==

1.2 此时页面报错是,缺少node-sass这个组件,我们下载这个组件之后,结果如图2,sass并没有渲染!

wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==

wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==

 

1.3 现在我们把sass单独成文件再引入css里面看看效果

wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==

结果和之前图二效果一样。

上网查询了一下,@import只能引入css文件,其他文件即使是预处理sass/less/stylus文件都不可以。

wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==

所以sass文件不应该引入到css文件里面,那究竟该引入到哪个文件里面呢?请看问题2

 

2 在使用webpack打包的情况下,如果sass是单独的文件,我该把这个文件引入到js文件里还是css文件里,还是html文件里?

问题一排除了引入css文件里面这个可能。那么我们试试引入html文件里。结果报了如下的错误:

localhost/:1 Refused to apply style from 'http://localhost:8083/index/index.scss' because its MIME type ('text/html') is not a supported stylesheet MIMEtype, and strict MIME checking is enabled.

大概意思是sass文件不是所支持的mine文件类型,所以找不到对应的解析方式。

MIME(Multipurpose Internet Mail Extensions)多用途互联网邮件扩展类型。是设定某种扩展名的文件用一种应用程序来打开的方式类型,当该扩展名文件被访问的时候,浏览器会自动使用指定应用程序来打开。

以我所看,link标签是一个比较古老的标签,只能解析一些常规的文件类型,所以sass这种较新的文件不能由link标签引入。

所以现在只有一种情况了,就是js里引入sass,如下所示,

wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==

wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==

F12打开看一下head标签里,还可以看到sass文件是通过style标签引入,而css文件是link标签引入的,因为css文件用了ExtractTextPlugin插件单独成一个文件,所以link标签引入,而sass没有用,所以是style引入。

wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==

3 为什么sass下载之后不需要import之后才能使用

 

10 postcss-loader

这个loader的作用是给css自动加上前缀,并且这个loader自己也需要插件,单独写在postcss.config.js文件里面。

为什么在webpack配置文件里面没有引入postcss文件呢,像其他插件一样?因为postcss是一个loader,webpck里面loader都是直接用,而不是像插件那样引入的。但是postcss配置文件里面,它自己的插件autoprefixer是require引入的。

webpack.config.js

{
            test: /\.css$/,
            use: ExtractTextPlugin.extract({
                fallback: "style-loader",
                use: ["css-loader","postcss-loader"],
                publicPath: '../'
              }),
          },

wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==

postcss.config.js

module.exports = {
  plugins: [
    require('autoprefixer')
  ]
}

wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==

可以看到确实已经加上前缀了

wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==

但是如果在sass里面写则没有效果,毕竟sass没

 

有加这个loader

{
            test: /\.(sass|scss)$/,
            use:['style-loader','css-loader','sass-loader','postcss-loader']
          },

wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==

像这样加上postcss-loader就好了。

wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==

 

11 PurifyCSS Plugin

这个插件的作用在于将link引入的css与html对比,把不存在的一些样式删除,从而达到优化。而既然是link引入的那么这个插件建议和能把css单独打包成单独的文件插件Extract Text plug

in一起使用。

You can also use the file plugin to drop a CSS file into your output folder, but it is highly recommended to use the PurifyCSS plugin with the Extract Text plugin

如果要搜索多个路径里面的文件进行对比,需要下载glob-all

In order to use this plugin to look into multiple paths you will need to:

  1. npm install --save glob-all
  2. Add const glob = require('glob-all'); at the top of your webpack config
  3. Then you can pass your paths to an array, like so:

我们现在css文件和sass文件里面添加一些冗余的样式:

wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==

wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==

 

12 SourceMap

webpack3中,开启调试需要下载sourceMap

webpack4中,直接 --mode development就默认开启调试了。可以看到下左图,我们npm run dev之后打开source里面webpack下能看到我们的源码。

下右图是npm run build也就是--mode production得到的打包的文件,里面就没有我们的源码。wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==

 

13 babel

babel的是js编译器,他的主要用处有两个,一是将ES新语法转化为浏览器能够识别的旧语法,而是转化jsx语法。

使用babel需要下载以下几个模块:

1.babel-core:babel转译器本身,提供了babel的转译API,如babel.transform等,用于对代码进行转译。像webpack的babel-loader就是调用这些API来完成转译过程的。

之前版本babel只要安装一个babel就可以用了,所以之前的版本包含了一大堆的东西,这也导致了下载一堆不必要的东西。但在babel 6中,将babel拆分成两个包:babel-cli和babel-core。如果你想要在CLI(终端或REPL)使用babel就下载babel-cli,如果想要在node中使用就下载babel-core。


2.babel-loader:真正作用的loader,babel-core是他的一个插件。就像postcss的需要一个主要的autofixer插件一样。

3.babel-present-env/babel-preset-react:是一个帮你配置babel的preset,根据配置的目标环境自动采用需要的babel插件。 其中babel-core和babel-loader是核心插件,babel-preset-env 和 babel-preset-react 是处理代码的两个预设。

同时配置babel需要一个.babelrc的配置文件,存放在项目的根目录下.

{
    "presets": [
        "env" //表示其中一种预设为env,即转化js新语法为旧语法
        "react" //表示其中一种预设为jsx,即转化jsx语法为一般js
    ]
}

wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==

当然要使用react的jsx 还需要下载babel-preset-react

import './index.css';
import './index.scss';
import React, {Component} from 'react';
import ReactDOM from 'react-dom';

ReactDOM.render(
    <div>我是react</div>,
    document.querySelector('#app')
)
const temp = document.getElementById('app');
temp.style.color = 'pink';

wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==

14 CommonChunkPlugin

webpack4里面已经废除了该插件,新版的我们后续再讨论,先看看webpack3中的用于提取分离 ①公共代码  ②webpack执行文件  ③第三方库   的插件CommonChunkPlugin

1.为什么要提取公共部分?

wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==

我的项目文件如图,其中a.js和b.js都引入了common.js这个文件以及jq文件,然后在index.html中引入了a.js和b.js. 设想如果我们不提取公共部分common.js和jq,那么a会引入一次,b也会引入一次导致重复引入,导致首屏加载的bundle文件或者按需加载的bundle文件体积过大,从而导致加载时间过长,造成白屏问题。所以如果我们把公共部分提取出来在最后一次引用就可避免这样的问题。

CommonsChunkPlugin 插件,是一个可选的用于建立一个独立文件(又称作 chunk)的功能,这个文件包括多个入口 chunk 的公共模块。通过将公共模块拆出来,最终合成的文件能够在最开始的时候加载一次,便存到缓存中供后续使用。这个带来速度上的提升,因为浏览器会迅速将公共的代码从缓存中取出来,而不是每次访问一个新页面时,再去加载一个更大的文件。

 

2.项目文件信息

a.js

wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==

b.js

wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==

common.js

wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==

 

3.不提取公共代码的情况

打包后的文件a和b大小分别为275kb

wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==

并且他们里面都存在公共代码common.js和第三方库jq的文件内容

wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==

 

wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==

 

4. 提取所有公共代码

webpack配置如下,如果没有配置chuncks的话,代码默认提取所有入口文件的公共部分,在本项目中代码默认提取a.js和b.js的公共部分。name属性代表文件的名字,如果和入口文件一致,代表打包好之后的文件合并到该入口文件中,如果没有就生成一个新的文件名为name的js文件。

const webpack = require("webpack");
module.exports = {
	entry: {
		a: "./src/a.js",
		b: "./src/b.js",
	},
	output: {
		path: __dirname + "/dist",
		filename: "[name].js"
	},
	plugins: [
        new webpack.optimize.CommonsChunkPlugin({
            name: 'common',
            filename: '[name].js',
            //chuncks:'[XXX,XXX]'
        }),
	]
}

wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==

打包结果如下,可以看到a.js和b.js的文件大小为679byte,明显比之前小了。并且打包结果多出一个叫common.js的文件,里面装的就是提取出的公共部分~ 此时的打包出的common.js文件中有三个部分 是ab都引入的common.js   是ab都引入的jq   是webpack执行文件,这三个部分的单独抽出是有顺序的,需先抽离webpack执行代码和第三方库 然后再抽离公共部分代码

wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==

 

5 提取webpack执行文件

为什么要单独抽离webpack执行文件呢?为了浏览器缓存,因为每次打包之后的webpack执行文件都是不一样的,所以里面的hash值也不一样,对于浏览器来说就是完全不同的文件,所以也就不能使用缓存了。

plugins: [
		new webpack.optimize.CommonsChunkPlugin({
	            name: ['vendor','runtime'],
	            filename: '[name].js',
	            minChunks: Infinity
	        }),
	]

其实上面这段代码,等价于下面这段:

 plugins: [
        new webpack.optimize.CommonsChunkPlugin({
            name: 'vendor',
            filename: '[name].js'
        }),
        new webpack.optimize.CommonsChunkPlugin({
            name: 'runtime',
            filename: '[name].js',
            chunks: ['vendor']
        }),
    ]

意思是,先抽离一个名为vender的公共文件,再从vender文件中抽离出webpack运行文件,名为runtime。

webpack打包结果如下,可以看到之前打包的公共部分文件common.js拆分成vender.js和runtime.js两个部分。

在runtime文件中只有webpack运行文件,剩余的公共引入common.js内容和jq内容则在vender.js中(如下图)。

 

6 从vender文件中提取第三方库

const webpack = require("webpack");
const packagejson = require("./package.json");
module.exports = {
	entry: {
		a: "./src/a.js",
		b: "./src/b.js",
		vendor: Object.keys(packagejson.dependencies)
	},
	output: {
		path: __dirname + "/dist",
		filename: "[name].js"
	},
	plugins: [
		new webpack.optimize.CommonsChunkPlugin({
	            name: ['vendor','runtime'],
	            filename: '[name].js',
	            minChunks: Infinity
	        }),
        new webpack.optimize.CommonsChunkPlugin({
            name: 'common',
            filename: '[name].js',
            chunks: ['a','b']
        }),
	]
}

打包结果如下,vendor文件大小还是272kb没变化(可能是因为我的common.js文件太小了),打包多出了一个common.js文件,这就是把之前vender文件中公共部分抽离出来的结果。

现在分别来看看抽离出的三个文件:

① vendor.js 里面只有第三方库jq

② common.js 里面只有公共代码

③ runtime.js 里面只有webpack执行代码

 

7 注意点

虽然公共代码 第三方库等都打包好了,但是它们并不会自动引入到index.html文件中,所以要么你手动引入一下,要么就是把公共部分合并到一个入口文件中去,一起引入。

我的index.html文件

<!DOCTYPE html>
<html>
<head>
	<title></title>
</head>
<body>
	
</body>
<script type="text/javascript" src="../dist/a.js"></script>
<script type="text/javascript" src="../dist/b.js"></script>
</html>

如果不引入就会像这样报错

 

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值