3

刚接触webpack,在网上看了些入门的教程和资料,在此作下记录。

什么是webpack?

简单说就是模块加载器,本文不作过多的介绍。

安装webpack

首先确保你的机器已经安装了Node.js和npm(安装方式请参考其他相关资料)。
第一步,为你的项目新建一个文件夹,然后输入 npm init,然后填写相关问题。
这样会为你创建了 package.json。
第二步,接下来我们安装 Webpack,我们要把它安装在本地,输入 npm i webpack --save-dev
到此就完成了webpack的安装了。

项目目录

  • /app
    main.js
    component.js

  • /build
    bundle.js (自动创建)
    index.html

package.json
webpack.config.js


我们会使用 Webpack 在我们的 /app 里来自动创建 bundle.js 。接下来,我们来设置 webpack.config.js。

设置webpack

webpack.config.js文件设置

var path = require('path');

module.exports = {
    entry: path.resolve(__dirname, 'app/main.js'),
    output: {
        path: path.resolve(__dirname, 'build'),
        filename: 'bundle.js',
    },
};

按上述项目目录时,__dirname可写为''

运行一个HelloWorld demo

经过上述的配置,我们已经有了一个最简单的配置了,下面我们用它来编译一个简单的Hello World。

  • app/component.js

'use strict';

module.exports = function () {
    var element = document.createElement('h1');

    element.innerHTML = 'Hello world';

    return element;
};
  • app/main.js

'use strict';
var component = require('./component.js');

document.body.appendChild(component());

然后在你的命令行运行 webpack,接着你可以看到应用会开始编译,一个 bundle.js 文件会这样出现在 /build 文件夹下。

  • build/index.html

<!DOCTYPE html>
<html>
  <head>
    <meta charset="UTF-8"/>
  </head>
  <body>
    <script src="bundle.js"></script>
  </body>
</html>

我们在index.html中引入刚才编译好的bundle.js,我们可以打开 index.html,在浏览器中预览一下效果。

设置 package.json scripts

npm是一个非常好用的用来编译的指令,通过 npm 你可以不用去担心项目中使用了什么技术,你只要调用这个指令就可以了,只要你在 package.json 中设置 scripts 的值就可以了。
接下来我们把编译通过 npm run build 来执行:
把下面的内容添加到 package.json中。

"scripts": {
    "build": "webpack"
}

现在你可以输入 npm run build 就可以编译了。

开始工作流

每次编译都需要输入npm run build,想必大家都不愿意,下面我们使用webpack-dev-server在每次文件改变后自动执行编译。

设置webpack-dev-server

第一步需要安装webpack-dev-server,在命令行中输入 npm i webpack-dev-server --save,安装完成后我们需要调整package.jsonscripts 部分去包含这个指令。

  • package.json

{
  "scripts": {
    "build": "webpack",
    "dev": "webpack-dev-server --devtool eval --progress --colors --hot --content-base build"
  }
}

配置完成后,我们可以在命令行里运行 npm run dev ,运行的时候他会执行 dev 属性里的值。编译完成后,我们可以访问"http://localhost:8080" 看到效果。
上述配置顶的意义:
1、webpack-dev-server - 在 localhost:8080 建立一个 Web 服务器
3、devtool eval - 为你的代码创建源地址。当有任何报错的时候可以让你更加精确地定位到文件和行号
4、progress - 显示合并代码进度
5、colors - 命令行中显示颜色!
6、content-base build - 指向设置的输出目录

让浏览器自动刷新

当运行 webpack-dev-server 的时候,它会监听你的文件修改。当项目重新合并之后,会通知浏览器刷新。为了能够触发这样的行为,你需要把你的 index.html 放到 build/ 文件夹下,然后做这样的修改:

  • build/index.html

<!DOCTYPE html>
<html>
  <head>
    <meta charset="UTF-8"/>
  </head>
  <body>
    <script src="http://localhost:8080/webpack-dev-server.js"></script>
    <script src="bundle.js"></script>
  </body>
</html>

我们需要增加一个脚本当发生改动的时候去自动刷新应用,你需要在配置中增加一个入口点。

var path = require('path');

module.exports = {
    entry: ['webpack/hot/dev-server', path.resolve(__dirname, 'app/main.js')],
    output: {
        path: path.resolve(__dirname, 'build'),
        filename: 'bundle.js',
    },
};

按上述目录时,__dirname可设置为''

就是这样!现在你的应用就可以在文件修改之后自动刷新了。

模块

Webpack 允许你使用不同的模块类型,但是 “底层”必须使用同一种实现。所有的模块可以直接在盒外运行。

ES6 模块

import MyModule from './MyModule.js';

CommonJS

var MyModule = require('./MyModule.js');

AMD

define(['./MyModule.js'], function (MyModule) {
});

理解文件路径

一个模块需要用它的文件路径来加载,看一下下面的这个结构:

--app
------modules
-----------MyModule.js
------main.js (entry point)
------utils.js

打开 main.js 然后可以通过下面两种方式引入 app/modules/MyModule.js

  • app/main.js

// ES6
import MyModule from './modules/MyModule.js';

// CommonJS
var MyModule = require('./modules/MyModule.js');

最开始的 ./ 是 “相对当前文件路径”
让我们打开 MyModule.js 然后引入 app/utils:

  • app/modules/MyModule.js

// ES6 相对路径
import utils from './../utils.js';

// ES6 绝对路径
import utils from '/utils.js';

// CommonJS 相对路径
var utils = require('./../utils.js');

// CommonJS 绝对路径
var utils = require('/utils.js');

相对路径是相对当前目录。绝对路径是相对入口文件,这个案例中是 main.js。

安装ReactJs

在命令行在输入npm install react --save

在代码中使用 ReactJS

  • component.jsx

import React from 'react';

export default class Hello extends React.Component {
  render() {
    return <h1>Hello world</h1>;
  }
}
  • main.js

import React from 'react';
import Hello from './component.jsx';

main();

function main() {
    React.render(<Hello />, document.getElementById('app'));
}
  • build/index.html

<!DOCTYPE html>
<html>
  <head>
    <meta charset="UTF-8"/>
  </head>
  <body>
    <div id="app"></div>

    <script src="http://localhost:8080/webpack-dev-server.js"></script>
    <script src="bundle.js"></script>
  </body>
</html>

转换 JSX

为了能够使用 JSX 语法,你需要用 Webpack 来转码你的 JavaScript,这是加载器的工作,我们可以使用一个很好用也有很多功能的 Babel。

npm install babel-loader --save-dev

现在我们需要去配置 Webpack 来使用加载器。

  • webpack.config.js

var path = require('path');
var config = {
  entry: ['webpack/hot/dev-server', path.resolve('', 'app/main.js')],
  output: {
    path: path.resolve(__dirname, 'build'),
    filename: 'bundle.js'
  },
  module: {
    loaders: [{
      test: /\.jsx?$/, // 用正则来匹配文件路径,这段意思是匹配 js 或者 jsx
      loader: 'babel' // 加载模块 "babel" 是 "babel-loader" 的缩写
    }]
  }
};

module.exports = config;

在命令行中运行 npm run dev,然后刷新页面就可以看到修改。

优化重合并

你可能注意到在引入 React JS 到你的项目之后,给你的应用重新合并会花费太多的时间。在开发环境中,最理想的是编译最多 200 到 800 毫秒的速度,取决于你在开发的应用。
在开发环境中使用压缩文件
为了不让 Webpack 去遍历 React JS 及其依赖,你可以在开发中重写它的行为。

  • webpack.config.js

var path = require('path');
var node_modules = path.resolve(__dirname, 'node_modules');
var pathToReact = path.resolve(node_modules, 'react/dist/react.min.js');

config = {
    entry: ['webpack/hot/dev-server', path.resolve(__dirname, 'app/main.js')],
    resolve: {
        alias: {
          'react': pathToReact
        }
    },
    output: {
        path: path.resolve(__dirname, 'build'),
        filename: 'bundle.js',
    },
    module: {
        loaders: [{
            test: /\.jsx?$/,
            loader: 'babel'
        }],
        noParse: [pathToReact]
    }    
};

module.exports = config;

我们在配置中做了两件事:
1、不管 “React” 是什么时候在代码中引入的,它会去匹配压缩后的 React JS 文件取代去 node_modules 中遍历。
2、不管 Webpack 什么时候试图是解析压缩文件,我们阻止它,告诉它那不是必须的。

加载CSS

Webpack允许像加载任何代码一样加载 CSS。你可以选择你所需要的方式,但是你可以为每个组件把所有你的 CSS 加载到入口主文件中来做任何事情。
加载 CSS 需要 css-loader 和 style-loader,他们做两件不同的事情,css-loader会遍历 CSS 文件,然后找到 url() 表达式然后处理他们,style-loader 会把原来的 CSS 代码插入页面中的一个 style 标签中。
安装加载器
在命令行中输入npm install css-loader style-loader --save-dev
安装完毕后可以将加载器配置到 Webpack.config.js 文件中。

  • webpack.config.js

var path = require('path');
var config = {
  entry: ['webpack/hot/dev-server', path.resolve(__dirname, 'app/main.js')],
  output: {
    path: path.resolve(__dirname, 'build'),
    filename: 'bundle.js'
  },
  module: {
    loaders: [{
      test: /\.jsx$/,
      loader: 'jsx'
    }, {
      test: /\.css$/, // Only .css files
      loader: 'style!css' // Run both loaders
    }]
  }
};

module.exports = config;

加载 CSS 文件
加载一个 CSS 文件就和加载其他文件一样:

  • main.js

import './main.css';
// Other code
  • Component.jsx

import './Component.css';
import React from 'react';

export default React.createClass({
  render: function () {
    return <h1>Hello world!</h1>
  }
});

将所有CSS合并成一个
在你的主入口文件中个,比如 app/main.js 你可以为整个项目加载所有的 CSS:

  • app/main.js

import './project-styles.css';
// 其他 JS 代码

CSS 就完全包含在合并的应用中,再也不需要重新下载。
如果你想发挥应用中多重入口文件的优势,你可以在每个入口点包含各自的 CSS:

  • app/main.js

import './style.css';
// 其他 JS 代码

  • app/entryA/main.js

import './style.css';
// 其他 JS 代码
  • app/entryB/main.js

import './style.css';
// 其他 JS 代码

你把你的模块用文件夹分离,每个文件夹有各自的 CSS 和 JavaScript 文件。再次,当应用发布的时候,导入的 CSS 已经加载到每个入口文件中。
具体的组件
你可以根据这个策略为每个组件创建 CSS 文件,可以让组件名和 CSS 中的 class 使用一个命名空间,来避免一个组件中的一些 class 干扰到另外一些组件的 class

  • app/components/MyComponent.css

.MyComponent-wrapper {
  background-color: #EEE;
}

  • app/components/MyComponent.jsx

import './MyComponent.css';
import React from 'react';

export default React.createClass({
  render: function () {
    return (
      <div className="MyComponent-wrapper">
        <h1>Hello world</h1>
      </div>
    )
  }
});

使用内联样式取代 CSS 文件
在 “React Native” 中你不再需要使用任何 CSS 文件,你只需要使用 style 属性,可以把你的 CSS 定义成一个对象,那样就可以根据你的项目重新来考略你的 CSS 策略。

  • app/components/MyComponent.jsx

import React from 'react';

var style = {
  backgroundColor: '#EEE'
};

export default React.createClass({
  render: function () {
    return (
      <div style={style}>
        <h1>Hello world</h1>
      </div>
    )
  }
});

_rex_
180 声望4 粉丝

努力做个全栈工程师