昨天今天一直在捣腾react和webpack结合,巨坑。。。心累。。。昨天差点就要放弃了,可是晚上想想又不甘心。。。今天又来苦逼地看文档。。。总算有个初步的结果!(具体坑就不详细写了,又多又细又杂@-@)。
因为电脑曾经安装过appcan,这家伙自带了node10.38版本,安装webpack需要node版本大于12,折腾了半天总算弄明白啥回事,果断卸载了appcan。
webpack
WebPack是前端资源模块化管理和打包工具:它可以将许多松散的模块按照依赖和规则打包成符合生产环境部署的前端资源。还可以将按需加载的模块进行代码分隔,等到实际需要的时候再异步加载。通过loader
的转换,任何形式的资源都可以视作模块,比如 CommonJs 模块、 AMD 模块、 ES6 模块、CSS、图片、 JSON、Coffeescript、 LESS 等。
Webpack的工作方式是:把你的项目当做一个整体,通过一个给定的主文件(如:app.js),Webpack将从这个文件开始找到你的项目的所有依赖文件,使用loaders处理它们,最后打包为一个浏览器可识别的JavaScript文件。
安装
首先安装nodejs
Webpack可以使用npm安装,新建一个空的练习文件夹(此处命名为webpack sample progect),在终端中转到该文件夹后执行下述指令就可以完成安装。
/全局安装
npm install -g webpack
//安装到你的项目目录
npm install --save-dev webpack
使用Webpack前的准备
在终端中使用npm init
命令可以自动创建这个package.json文件
package.json文件已经就绪,我们在本项目中安装Webpack作为依赖包
// 安装Webpack
npm install --save-dev webpack
回到之前的空文件夹,并在里面创建两个文件夹, js文件夹和build文件夹,js文件夹用来存放原始数据和我们将写的JavaScript模块,build文件夹用来存放准备给浏览器读取的数据(包括使用webpack生成的打包后的js文件)。还需要创建几个文件,index.html 文件放在主文件夹中,手写app.js文件放在app文件夹中
index.html文件只有最基础的html代码,它唯一的目的就是加载打包后的js文件
创建webpack.config.js配置文件
var path = require("path");
module.exports = {
entry: {
app: ["./js/app.js"]
},
output: {
path: path.resolve("./build"),
filename: "main.js"
},
}
终端输入webpack(可以自动创建build文件夹和main.js)
热加载模式(自动刷新)的实现
本地开发服务器
热加载指览器监测代码的修改,并自动刷新修改后的结果,其实Webpack提供一个可选的本地开发服务器,这个本地服务器基于node.js构建,可以实现想要的这些功能,不过它是一个单独的组件,在webpack中进行配置之前需要单独安装它作为项目依赖
npm install webpack-dev-server --save-dev
完成之后输入,指使用webpack打包并启动webpack服务器,使用自动加载
webpack && webpack-dev-server --hot --inline
这句话特长,每次在终端敲会很烦,因此修改package.json的script,添加npm的命令start
{
"name": "webpacktest",
"version": "1.0.0",
"description": "just for webpack",
"main": "index.js",
"scripts": {
"start": "webpack && webpack-dev-server --hot --inline"
},
"author": "heyue",
"license": "ISC",
"devDependencies": {
"webpack": "^2.2.1",
"webpack-dev-server": "^2.4.2"
}
}
这样就只要输入:npm start 即可
使用第三方库
在webpack中使用第三方库,只需要在根目录使用npm install packageName
下载安装需要的库,然后在webpack页面中通过require()的形式加载进来,就可以直接使用了。如jquery。
npm install jquery
在js中
var $ = require('jquery');
Loaders
Loaders是webpack中最让人激动人心的功能之一了。通过使用不同的loader,webpack通过调用外部的脚本或工具可以对各种各样的格式的文件进行处理,比如说分析JSON文件并把它转换为JavaScript文件,或者说把下一代的JS文件(ES6,ES7)转换为现代浏览器可以识别的JS文件。或者说对React的开发而言,合适的Loaders可以把React的JSX文件转换为JS文件。
Loaders需要单独安装并且需要在webpack.config.js下的modules
关键字下进行配置
Loaders的配置选项包括以下几方面:
test
:一个匹配loaders所处理的文件的拓展名的正则表达式(必须)
loader
:loader的名称(必须)
include/exclude
:手动添加必须处理的文件(文件夹)或屏蔽不需要处理的文件(文件夹)(可选);
query
:为loaders提供额外的设置选项(可选)
下面以我用到的Bable为例
Babel 其实是一个编译JavaScript的平台,它的强大之处表现在可以通过编译帮你达到以下目的:
1)下一代的JavaScript标准(ES6,ES7),这些标准目前并未被当前的浏览器完全的支持;
2)使用基于JavaScript进行了拓展的语言,比如React的JSX
如何查找加载器babel?
在英文文档中找到 list of loader,找到babel
点击进入github,在文档中找到npm安装命令和配置方法:
npm install --save-dev babel-loader babel-core babel-preset-env webpack
module: {
rules: [
{
test: /\.js$/,
exclude: /(node_modules|bower_components)/,
use: {
loader: 'babel-loader',
options: {
presets: ['env']
}
}
}
]
}
测试
将前一篇文章中的react代码来测试
注意可以使用es6语法引入react和reactdom,可以直接写名字不加路径
import React from "react";
import ReactDOM from "react-dom";
import React from "react";
import ReactDOM from "react-dom";
var namelist=[
{
id: 1,
name: "Emma",
gender: "female"
},
{
id: 2,
name: "Jerry",
gender: "male"
},
{
id: 3,
name: "Loura",
gender: "female"
}
];
var Bodylist = React.createClass({
getInitialState: function(){
return {ischecked:false};
},
toggle: function(e){
this.setState({ ischecked:e.target.checked });
},
render: function(){
return(
<tbody>
<tr className={this.state.ischecked ? 'active' : ''}>
<td>{this.props.user.name}</td>
<td>{this.props.user.gender}</td>
<td><input type="checkbox" onClick={this.toggle} /></td>
</tr>
</tbody>
);
}
});
var Toplist = React.createClass({
render: function(){
return(
<table>
<caption>一个小例子</caption>
<thead>
<tr><th>name</th><th>gender</th></tr>
</thead>
{
namelist.map(function(user){
return(<Bodylist user={user} key={user.id} />);
})
}
</table>
);
}
});
ReactDOM.render(
<Toplist/>,
document.getElementById("example")
)
运行 npm start
浏览器打开localhost:8080即可出现表格
一切皆模块
Webpack有一个不可不说的优点,它把所有的文件都可以当做模块处理,包括你的JavaScript代码,也包括CSS和fonts以及图片等等等,只有通过合适的loaders,它们都可以被当做模块被处理。
css
webpack提供两个工具处理样式表,css-loader
和 style-loader
,二者处理的任务不同,css-loader
使你能够使用类似@import
和url(...)
的方法实现require()
的功能,style-loader
将所有的计算后的样式加入页面中,二者组合在一起使你能够把样式表嵌入webpack打包后的JS文件中。
CSS modules 的技术就意在把JS的模块化思想带入CSS中来,通过CSS模块,所有的类名,动画名默认都只作用于当前模块。Webpack从一开始就对CSS模块化提供了支持,在CSS loader中进行配置后,你所需要做的一切就是把”modules“传递都所需要的地方,然后就可以直接把CSS的类名传递到组件的代码中,且这样做只对当前组件有效,不必担心在不同的模块中具有相同的类名可能会造成的问题。
接着需要在js文件里,通过require的方式来引入css,我们来看具体的方法,首先需要安装css-loader、style-loader(安装style-loader的目的是为了在html中以style的方式嵌入css)。
npm install css-loader,style-loader --save-dev
在webpack.config,js的loader中加入:
{
test: /\.css$/,
use: [ 'style-loader', 'css-loader' ]
}
然后在app.js中:
require('./app.css');
或者
import css from './app.css';
CSS预处理器
Sass 和 Less之类的预处理器是对原生CSS的拓展,CSS预处理器可以这些特殊类型的语句转化为浏览器可识别的CSS语句,
在webpack里使用相关loaders进行配置就可以使用了,以下是常用的CSS 处理loaders
Less Loader
Sass Loader
Stylus Loader
PostCSS
以less为例;
进入webpack官方文档中list of loader,找到less打开
npm install --save-dev less-loader less接下来,在webpack配置文件中进行设置,
{
test: /\.less$/,
use: [{
loader: "style-loader" // creates style nodes from JS strings
}, {
loader: "css-loader" // translates CSS into CommonJS
}, {
loader: "less-loader" // compiles Less to CSS
}]
}
然后在app.js中引入就ok啦:
//import css from './style.less';
require('./style.less')
总结
webpack.config.js
var path = require("path");
module.exports = {
entry: {
app: ["./app/app.js"]
},
output: {
path: path.resolve("./build"),
filename: "main.js"
},
module: {
loaders: [
{
test: /\.js$/,
exclude: /(node_modules|bower_components)/,
use: {
loader: 'babel-loader',
options: {
presets: ['env','react']
}
}
},
{
test: /\.css$/,
use: [ 'style-loader', 'css-loader' ]
},
{
test: /\.less$/,
use: [{
loader: "style-loader" // creates style nodes from JS strings
}, {
loader: "css-loader" // translates CSS into CommonJS
}, {
loader: "less-loader" // compiles Less to CSS
}]
}
]}
};
这份文件大概有四个配置项 entry , output , module , plugins .
entry :指定打包的入口文件,每有一个键值对,就是一个入口文件。
output :配置打包结果,path定义了输出的文件夹,filename则定义了打包结果文件的名称,filename里面的[name]会由entry中的键替换,例子中的 /build/bundle.js 便是生成的文件。
resolve :定义了解析模块路径时的配置,常用的就是extensions,可以用来指定模块的后缀,这样在引入模块时就不需要写后缀了,会自动补全.
module :定义了对模块的处理逻辑,这里可以用loaders定义了一系列的加载器,以及一些正则。当需要加载的文件匹配test的正则时,就会进行处理。这里我们使用了 react-hot 和 babel 。 babel-loader 是我们使用ES-6进行开发时用于生成JS文件。
最后我们生成了一个style.css仅仅做个例子,告诉我们如何引入样式文件,实际上我们可以加载诸如 sass-loader 这样的加载器。
loader 对文件进行处理,这正是webpack强大的原因。比如这里定义了凡是.js结尾的文件都是用babel-loader做处理,而.jsx结尾的文件会先经过jsx-loader处理,然后经过babel-loader处理。当然这些loader也需要通过npm install安装。
plugins : 这里定义了需要使用的插件,比如commonsPlugin在打包多个入口文件时会提取出公用的部分,生成common.js。