Webpack学习笔记(二)
上一篇,我们已经学习了webpack的单入口打包、多入口打包、es6语法转化、在js中使用css以及在js中引入图片。本篇内容,我们将继续学习webpack的一些其他知识。
demo06-CSS Module(css局部作用域)
项目结构:
总所周知,css的规则都是全局的,任何一个组件的样式规则,都对整个页面有效。产生局部作用域的唯一方法,就是使用一个独一无二的class名字,不会与其他选择器重名。这个就是css module的做法。
接下来,我们来看看webpack中是怎么实现的:
var React = require('react');
var ReactDOM = require('react-dom');
var style = require('./app.css');
ReactDOM.render(
<div>
<h1 className={style.h1}>Hello World</h1>
<h2 className="h2">Hello Webpack</h2>
</div>,
document.getElementById('example')
);
这里是main.jsx中的react组件,上面代码中,我们将样式文件app.css输入到style对象,然后引用style.h1代表一个class。
.h1 {
color:red;
}
:global(.h2) {
color: blue;
}
构建工具会将类名style.h1编译成一个哈希字符串,like this:
同时,app.css也会被编译。
._1yZB3Q5Xe45RPofl-yJAo3 {
color:red;
}
:global(.h2) {
color: blue;
}
这样一来,这个类名就独一无二了,只对example组件有效了,这里就形成了css局部作用域。
我们来看看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']
}
}
},
{
test: /\.css$/,
use: [
{
loader: 'style-loader'
},
{
loader: 'css-loader',
options: {
modules: true
}
}
]
}
]
}
};
在上述代码中,能够实现css局部作用域最关键的就是loader: ‘style-loader’,它有个配置选项modules:true,表示打开css modules功能。
demo07-UglifyJs Plugin(压缩插件)
项目结构:
浏览器从服务器访问网页时获取的JavaScript、CSS资源都是文本形式的,文件越大网页加载时间越长。 为了提升网页加速速度和减少网络传输流量,可以对这些资源进行压缩。 压缩的方法除了可以通过GZIP算法对文件压缩外,还可以对文本本身进行压缩。
对文本本身进行压缩的作用除了有提升网页加载速度的优势外,还具有混淆源码的作用。由于压缩后的代码可读性非常差,就算别人下载到了网页的代码,也大大增加了代码分析和改造的难度。
webpack允许你使用插件来扩展它的功能,这里的UglifyJs Plugin插件就是用来压缩js代码。同样的,这里引入的无论是loader还是插件,都需要事先安装依赖。这里我们使用的是uglifyjs-webpack-plugin插件。我们来看看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()
]
};
凡是需要使用插件,都必须在plugins这个数组中进行配置,它就是一个插件列表,数组中每一个值就对应一个插件,在这里配置好之后,我们打包后的js代码就被压缩了,like this:
!function(r){function e(n){if(t[n])return t[n].exports;var o=t[n]={i:n,l:!1,exports:{}};return r[n].call(o.exports,o,o.exports,e),o.l=!0,o.exports}var t={};e.m=r,e.c=t,e.d=function(r,t,n){e.o(r,t)||Object.defineProperty(r,t,{configurable:!1,enumerable:!0,get:n})},e.n=function(r){var t=r&&r.__esModule?function(){return r.default}:function(){return r};return e.d(t,"a",t),t},e.o=function(r,e){return Object.prototype.hasOwnProperty.call(r,e)},e.p="",e(e.s=0)}([function(r,e){var t="Hello";t+=" World",document.write("<h1>"+t+"</h1>")}]);
demo08-HTML Webpack Plugin and Open Browser Webpack Plugin
项目结构:
我们直接来看看webpack.config.js里的东西:
这里引入了HTML Webpack Plugin和Open Browser Webpack Plugin这两个插件,HTML Webpack Plugin的作用就是帮你书写index.html文件,而Open Browser Webpack Plugin的作用是用来执行webpack打包后帮你打开浏览器。
plugins插件列表中,插件的配置需要写在插件的括号内,是一个配置对象。具体插件的配置对象,可以查找webpack官网的配置。
demo09-Environment flags(环境标志-DefinePlugin)
在开发中,我们通常会设置一些环境变量供项目使用,但是不同的环境(开发环境、测试环境、生产环境)下,总会有一些不同配置,如果将这些环境所需的配置全部写在代码里面显然是不合适的。通常情况下,我们都会有一个配置文件,根据不同的环境配置不同的变量,然后当项目启动时去读取改文件。
DefinePlugin允许我们创建一个在编译时可以配置全局常量:
// 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]
};
这里配置一个全局常量 __ DEV __,可以在js文件中引入这个全局常量并作一些操作:
// main.js
document.write('<h1>Hello World</h1>');
if (__DEV__) {
document.write(new Date());
}
给配置的变量赋值:
demo10-Code splitting(代码分割)
在一些大型的web项目中,如果将所有的代码都打包压缩到一个文件,这显然是不科学的,这样对界面渲染、首屏加载时间来说都是很不友好的。webpack允许我们将代码分割成多个部分,还可以实现按需加载:
// a.js
module.exports = 'Hello World';
// 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应该被分开打包成一个单独的文件。这时,我们就实现了代码分割和按需加载了。