Webpack的使用

Posted ccclarity

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Webpack的使用相关的知识,希望对你有一定的参考价值。

一、安装:在全局环境下安装

$ npm i -g webpack webpack-dev-server

二、运行命令,如果不能自动打开网页,在浏览器的地址栏输入:http://127.0.0.1:8080

npm run dev

webpack是为浏览器构建javascript模块脚本的quan前端工具。它可以类似于Browserify一样,但是能做的更多。

$ browserify main.js > bundle.js
# be equivalent to
$ webpack main.js bundle.js

Webpack需要一个配置文件名叫webpack.config.js,是一个commonJS的模块。有了这个文件之后,可以调用webpack,不需要别的参数。一些常用的命令行:

webpack – building for development
webpack -p – building for production (minification)
webpack --watch – for continuous incremental building
webpack -d – including source maps
webpack --colors – making building output pretty

可以在package.json文件中对这些命令做个性化处理。

"scripts": {
    "dev": "webpack-dev-server --open",
    "build": "webpack -p"
  },

执行 npm run dev 就是执行 webpack-dev-server --open,npm run build就是执行webpack -p。

三、入口文件:是webpack用来读取以创建bundle.js的文件。Webpack根据webpack.config.js创建bundle.js。webpack.config.js代码如下:

module.exports = {
  entry: ./main.js,    // main.js是入口文件
  output: {
    filename: bundle.js
  }
};

 

四、多个入口文件:webpack.config.js

module.exports = {
  entry: {
    bundle1: ./main1.js,
    bundle2: ./main2.js
  },
  output: {
    filename: [name].js‘    /**注意[name]**/
  }
};

五、babel 加载器

加载器是预处理程序,在webpack构建过程之前转换应用程序的资源文件。例如,Bable-loader可以将JSX/ES6文件转换成正常的JS文件,之后Webpack开始构建这些JS文件。需要在webpack.config.js里配置module。

module.exports = {
  entry: ./main.jsx,
  output: {
    filename: bundle.js
  },
  module: {
    rules: [
      {
        test: /\.jsx?$/,
        exclude: /node_modules/,
        use: {
          loader: babel-loader,
          options: {
            presets: [es2015, react]   // 需要配置插件 babel-preset-es2015 和 babel-preset-react(安装) 
          }
        }
      }
    ]
  }
};

题外话:提醒一下JSX的格式

// main.jsx
const React = require(react);
const ReactDOM = require(react-dom);

ReactDOM.render(
  <h1>Hello, world!</h1>,
  document.querySelector(#wrapper)
);

 

六、css加载器 css-loader

webpack可以在JS文件中加载css文件,使用css-loader

webpack.config.js中的配置

module.exports = {
  entry: ./main.js,
  output: {
    filename: bundle.js
  },
  module: {
    rules:[
      {
        test: /\.css$/,
        use: [ style-loader, css-loader ]
      },
    ]
  }
};

需要两个加载器:css-loader 和 style-loader(为了向html代码中插入<style>标签)

 

七、Image loader

webpack.config.js代码:

module.exports = {
  entry: ./main.js,
  output: {
    filename: bundle.js
  },
  module: {
    rules:[
      {
        test: /\.(png|jpg)$/,
        use: [
          {
            loader: url-loader,
            options: {
              limit: 8192
            }
          }
        ]
      }
    ]
  }
};

main.js

var img1 = document.createElement("img");
img1.src = require("./small.png");
document.body.appendChild(img1);

var img2 = document.createElement("img");
img2.src = require("./big.png");
document.body.appendChild(img2);

url-loader会把图片类型的文件转换到img标签中,当图片的大小小于limit的值,会转换到data URL上??????

八、CSS Module

css-loader?modules 查询参数模块使CSS-modules提供了一个本地作用域的css,可以用:global(selector)关闭。

app.css

/* local scope */
.h1 {
  color:red;
}

/* global scope */
:global(.h2) {
  color: blue;
}

九、UglifyJS 插件。webpack有自己的插件系统来拓展它的功能,UglifyJS可以压缩输入文件bundle.js的JS代码。

main.js

var longVariableName = Hello;
longVariableName +=  World;
document.write(<h1> + longVariableName + </h1>);

webpack.config.js

var webpack = require(webpack);
var UglifyJsPlugin = require(uglifyjs-webpack-plugin);

module.exports = {
  entry: ./main.js,
  output: {
    filename: bundle.js
  },
  plugins: [
    new UglifyJsPlugin()
  ]
};

最后main.js会被压缩成:

var o="Hello";o+=" World",document.write("<h1>"+o+"</h1>")

十、HTML Webpack plugin 和 open browser webpack plugin

HTML Webpack plugin 可以创建一个index.html文件,open browser webpack plugin可以在webpack加载时打开一个新的浏览器标签页

十一、environment flag

就好像是设置一个变量,只有设置了这个变量的环境才可以访问某些代码,例如:

document.write(<h1>Hello World</h1>);

if (__DEV__) {
  document.write(new Date());
}

webpack.config.js

var webpack = require(webpack);

var devFlagPlugin = new webpack.DefinePlugin({
  __DEV__: JSON.stringify(JSON.parse(process.env.DEBUG || false))
});

module.exports = {
  entry: ./main.js,
  output: {
    filename: bundle.js
  },
  plugins: [devFlagPlugin]
};

发现package.json有这样的变化

{
  // ...
  "scripts": {
    "dev": "cross-env DEBUG=true webpack-dev-server --open",
  },
  // ...
}

十二、code splitting

对于很多大型网站应用来说,把所有的代码放在一个单独的文件里效率很低,webpack允许我们把一个大型的JS文件分割成几个块,如果在某些情况下只需要某些代码块,则可以俺需要加载这些块。webpack使用require.ensure来定义一个分割点。

main.js

require.ensure([./a], function (require) {
  var content = require(./a);
  document.open();
  document.write(<h1> + content + </h1>);
  document.close();
});

require.ensure告诉webpack ./a.js从bundle.js 分离了出来,建立了一个单独的块文件。webpack负责这些dependency,输出文件,和运行时间等,不需要在index.html和webpack.config.js添加其他的代码。webpack实际上建立了两个输出文件,bundle.js 和 0.bundle.js。Webpack实际上将main.js 和 a.js构建为不同的块(bundle.js 和 0.bundle.js),并在需要时从bundle.js加载0.bundle.js。

另外一种代码分割的方式 使用bundle-loader。

// main.js

// Now a.js is requested, it will be bundled into another file
var load = require(bundle-loader!./a.js);

// To wait until a.js is available (and get the exports)
//  you need to async wait for it.
load(function(file) {
  document.open();
  document.write(<h1> + file + </h1>);
  document.close();
});

十三、common chunk

当多个JS文件拥有公共块时,可以使用插件CommonsChunkPlugin将公共部分提取到一个单独的文件中,这有助于浏览器的缓存和节省带宽。

这里的代码不是很理解,先粘贴过来,再研究吧??????

// main1.jsx
var React = require(react);
var ReactDOM = require(react-dom);

ReactDOM.render(
  <h1>Hello World</h1>,
  document.getElementById(a)
);

// main2.jsx
var React = require(react);
var ReactDOM = require(react-dom);

ReactDOM.render(
  <h2>Hello Webpack</h2>,
  document.getElementById(b)
);
<html>
  <body>
    <div id="a"></div>
    <div id="b"></div>
    <script src="commons.js"></script>
    <script src="bundle1.js"></script>
    <script src="bundle2.js"></script>
  </body>
</html>
var webpack = require(webpack);

module.exports = {
  entry: {
    bundle1: ./main1.jsx,
    bundle2: ./main2.jsx
  },
  output: {
    filename: [name].js
  },
  module: {
    rules:[
      {
        test: /\.js[x]?$/,
        exclude: /node_modules/,
        use: {
          loader: babel-loader,
          options: {
            presets: [es2015, react]
          }
        }
      },
    ]
  },
  plugins: [
    new webpack.optimize.CommonsChunkPlugin({
      name: "commons",
      // (the commons chunk name)

      filename: "commons.js",
      // (the filename of the commons chunk)
    })
  ]
}

十四、Vendor clunk

可以将脚本中的供应商库从CommonsChunkPlugin中提取到单独的文件中。

main.js

var $ = require(jquery);
$(h1).text(Hello World);

index.html

<html>
  <body>
    <h1></h1>
    <script src="vendor.js"></script>
    <script src="bundle.js"></script>
  </body>
</html>

webpack.config.js

var webpack = require(webpack);

module.exports = {
  entry: {
    app: ./main.js,
    vendor: [jquery],    // jQuery包含在公共块vendor.js
  },
  output: {
    filename: bundle.js
  },
  plugins: [
    new webpack.optimize.CommonsChunkPlugin({
      name: vendor,
      filename: vendor.js
    })
  ]
};

ProvidePlugin 插件可以使一个变量在每个模块中像一个全局变量一样使用,不需要重新import或者require。

// main.js
$(h1).text(Hello World);


// webpack.config.js
var webpack = require(webpack);

module.exports = {
  entry: {
    app: ./main.js
  },
  output: {
    filename: bundle.js
  },
  plugins: [
    new webpack.ProvidePlugin({
      $: jquery,
      jQuery: jquery
    })
  ]
};

十五、exposing global variables 公开全局变量

如果想使用一些全局变量,但是不想使他们包含在Webpack包里,可以在webpack.config.js中启用external字段。

例如,新建一个data.js

// data.js
var data = Hello World;

index.html

<html>
  <body>
    <script src="data.js"></script>
    <script src="bundle.js"></script>
  </body>
</html>

但是此时,出口文件只有一个bundle.js 而不是data.js。data可以作为一个全局变量。

webpa.config.js

// webpack.config.js
module.exports = {
  entry: ./main.jsx,
  output: {
    filename: bundle.js
  },
  module: {
    rules:[
      {
        test: /\.js[x]?$/,
        exclude: /node_modules/,
        use: {
          loader: babel-loader,
          options: {
            presets: [es2015, react]
          }
        }
      },
    ]
  },
  externals: {
    // require(‘data‘) is external and available
    //  on the global var data
    data: data
  }
};

可以在我们的入口JS文件中使用这个全局变量。

// main.jsx
var data = require(data);
var React = require(react);
var ReactDOM = require(react-dom);

ReactDOM.render(
  <h1>{data}</h1>,
  document.body
);

也可以把react 和 react-dom 放入externals变量里,方便减少bundle.js的创建时间和大小。

 

UglifyJs Plugin

以上是关于Webpack的使用的主要内容,如果未能解决你的问题,请参考以下文章

如何使用webpack加载库源映射?

Vue报错:Uncaught TypeError: Cannot assign to read only property 'exports' of object 的解决方法(代码片段

报错:✘ http://eslint.org/docs/rules/indent Expected indentation of 0 s paces but found 2(代码片段

报错:✘ http://eslint.org/docs/rules/indent Expected indentation of 0 s paces but found 2(代码片段

无法创建中继容器; graphql.js 文件似乎有 webpack 工件?

浅析 -- webpack