webpack、sass、react、redux的简易demo入门

最开始只是想综合的初略学习下这几种技术,因此萌生了搭建一个简单的结构的想法;整个结构应该没有什么问题;已经放到了github上,地址:webpack、sass、react、redux的简易demo入门javascript

webpack

本质上,webpack 是一个现代 JavaScript 应用程序的静态模块打包器(module bundler)。当 webpack 处理应用程序时,它会递归地构建一个依赖关系图(dependency graph),其中包含应用程序须要的每一个模块,而后将全部这些模块打包成一个或多个 bundle。

我本身对webpack的使用也不是很熟练,尚未很明白webpack的设计思惟,因此在配置的时候也是一脸懵逼,跟着官方文档和一些社区的文章来一步一步配置,主要仍是须要知道这几个配置:css

  • 入口(entry)
  • 输出(output)
  • loader
  • 插件(plugins)
  • 解析(Resolve)

入口(entry)

起点或是应用程序的起点入口。从这个起点开始,应用程序启动执行。若是传递一个数组,那么数组的每一项都会执行。html

entry字段能够是string | [string] | object { <key>: string | [string] }或者是函数【函数返回值是上面的三种类型中的一种】,本次demo的选择是对象来处理,以下:java

entry: {
        home: './src/scripts/pages/home/index.js'
        // homecss: './src/styles/pages/home.scss'  // scss入口放到最开始的js中, webpack没法处理非js文件
    },

输出(output)

output 位于对象最顶级键(key),包括了一组选项,指示 webpack 如何去输出、以及在哪里输出你的「bundle、asset 和其余你所打包或使用 webpack 载入的任何内容」。

一般而言,经过 output.filename 和 output.path 属性,来告诉 webpack bundle 的名称,以及咱们想要生成(emit)到哪里。demo中的配置如:node

output: {
        path: path.join(__dirname + '/src/dist'),
        // publicPath:'/'
        // publicPath: path.join(__dirname + '/src/dist/'), // 加载外部资源,此选项指定在浏览器中所引用的「此输出目录对应的公开 URL」
        filename: 'js/[name].js'
    }

须要注意的是,filename: 'js/[name].js'这么写是由于webpack支持入口文件为多个文件时能够配置不一样的输出文件名,参考output-filenamereact

loader

loader 让 webpack 可以去处理那些非 JavaScript 文件(webpack 自身只理解 JavaScript)。loader 能够将全部类型的文件转换为 webpack 可以处理的有效模块,而后你就能够利用 webpack 的打包能力,对它们进行处理。本质上,webpack loader 将全部类型的文件,转换为应用程序的依赖图能够直接引用的模块。

重要的是要记得,在 webpack 配置中定义 loader 时,要定义在 module.rules 中,而不是 rules。webpack

module: {
        rules: [
            {
                test: /\.js$/,
                exclude: /(node_modules|bower_components)/,
                use: {
                    loader: 'babel-loader',
                    options: {
                        presets: ['@babel/preset-env', '@babel/stage-3', '@babel/react']
                    }
                }
            },
            {
                test: /\.scss$/,
                use: extractSass.extract({
                    use: [{
                        loader: "css-loader"
                    }, {
                        loader: "sass-loader"
                    }],
                    // publicPath: './../', // 加载外部资源,把路径从新定义到dist目录下,而不是css里面
                    // use style-loader in development
                    fallback: "style-loader"
                })
            },
            {
                test: /\.(png|svg|jpg|gif|jpeg)$/,
                use: [
                    {   
                        loader: 'file-loader',
                        options: {
                            name: '[name].[ext]',
                            useRelativePath: true, // 图片相对路径
                            outputPath: 'images/'
                        }
                    }
                ]
            }
            ]
    }

以上是demo的配置,在 webpack 的配置中 loader 有两个目标。git

  1. 识别出应该被对应的 loader 进行转换的那些文件。(使用 test 属性)
  2. 转换这些文件,从而使其可以被添加到依赖图中(而且最终添加到 bundle 中)(use 属性)

能够看到,同一个文件能够顺序使用多个loader来加载,每一个loader能够传递参数来进行特殊处理。github

插件(plugins)

插件是 wepback 的支柱功能。webpack 自身也是构建于,你在 webpack 配置中用到的相同的插件系统之上!插件目的在于解决 loader 没法实现的其余事。
webpack 插件是一个具备 apply 属性的 JavaScript 对象。apply 属性会被 webpack compiler 调用,而且 compiler 对象可在整个编译生命周期访问。

因为插件能够携带参数/选项,你必须在 webpack 配置中,向 plugins 属性传入 new 实例。根据你的 webpack 用法,这里有多种方式使用插件。插件使用插件列表web

demo中使用了两个pluginsextract-text-webpack-plugin & DefinePlugin,都是按照官方插件文档配置的。

解析(Resolve)

这些选项能设置模块如何被解析。webpack 提供合理的默认值,可是仍是可能会修改一些解析的细节。关于 resolver 具体如何工做的更多解释说明,请查看模块解析方式。

简单的说,就是会帮咱们弄好一些默认的选项,好比别名aliasextensions模块默认后缀、mainFiles默认文件入口等;

resolve: {
        mainFiles: ["index"],
        extensions: ['.js', '.jsx'],
        alias: {
            'stylepages': path.join(__dirname + '/src/styles/pages'),
            'scripts': path.join(__dirname + '/src/scripts/pages'),
            'commonjs': path.join(__dirname + '/src/scripts/common')
        }
    }

遇到问题

关于webpack没法把css文件做为入口,须要在js中引入css,而后进行css的分离

关于sass使用@import时来使用alias别名配置的路径时不被正确解析,sass-loader须要在使用别名的前面加上~,stylelib是别名,使用时@import '~stylelib/base.scss';

关于sass和图片等外部资源的打包出现的路径不一致,,有如下几种方法:

  • 第一种方法,能够在配置fileloader的时候使用相对路径:useRelativePath
{
    test: /\.(png|svg|jpg|gif|jpeg)$/,
         use: [
           {   
              loader: 'file-loader',
               options: {
                   name: '[name].[ext]',
                   useRelativePath: true, // 图片相对路径
                   outputPath: 'images/'
                 }
              }
          ]
}
  • 第二种方法,在使用ExtractTextWebpackPlugin的时候,能够根据已有的loader来从新提取loader,在提取新的loader时,能够配置公共路径publicPath
const ExtractTextPlugin = require("extract-text-webpack-plugin");

const extractSass = new ExtractTextPlugin({
    filename: "css/[name].css",
    disable: process.env.NODE_ENV === "development"
});


// loader 里面
{
   test: /\.scss$/,
   use: extractSass.extract({
         use: [{
                loader: "css-loader"
              }, {
                 loader: "sass-loader"
              }],
       publicPath: './../', // 把路径从新定义到dist目录下,而不是css里面
       // use style-loader in development
       fallback: "style-loader"
    })
}
  • 第三种方法,直接在全部的输出目录处使用当前的打包路径,publicPath
output: {
     path: path.join(__dirname + '/src/dist'),
     publicPath:'./'
     // publicPath: path.join(__dirname + '/src/dist/'), // 加载外部资源,此选项指定在浏览器中所引用的「此输出目录对应的公开 URL」
     filename: 'js/[name].js'
    }

sass

Sass 是一款强化 CSS 的辅助工具,它在 CSS 语法的基础上增长了变量 (variables)、嵌套 (nested rules)、混合 (mixins)、导入 (inline imports) 等高级功能,这些拓展令 CSS 更增强大与优雅。使用 Sass 以及 Sass 的样式库(如 Compass)有助于更好地组织管理样式文件,以及更高效地开发项目。

使用sass能够感觉到如下几点的优点:

  1. 合理的嵌套规则,不须要重复书写selector。
  2. 变量$、占位符%均可以很好的提供复用性
  3. 函数、运算能够很好的增长灵活性

这里就很少说sass的学习了,能够查看sass中文sass官网

react

React 是一个采用声明式,高效并且灵活的用来构建用户界面的框架。
学习react的重要内容包括:
  1. jsx的书写语法
  2. 组件Components【props、state、Lifecycle...】
  3. 虚拟dom,
  4. 组件渲染和diff,Lists and Keys

更多的学习react学习官网

redux

Redux 是 JavaScript 状态容器,提供可预测化的状态管理。应用中全部的 state 都以一个对象树的形式储存在一个单一的 store 中。 唯一改变 state 的办法是触发 action,一个描述发生什么的对象。 为了描述 action 如何改变 state 树,你须要编写 reducers;
  1. 应用中全部的 state 都以一个对象树的形式储存在一个单一的 store 中,初始时由reducer初识态来建立
  2. 改变state的惟一方法就是触发dispatch一个action,
  3. 一个action是本质上一个对象,用来把最新的数据传到store的有效载荷
  4. Reducer就是把action这个有效载荷解析,并应用到store之中;

具体实践中:

  1. 书写reducer,来肯定初始时的state
  2. 根据初始reducer来建立store,并使用store.subscribe来监听store变化时的操做
  3. 书写action,来承载每次修改store的变化
  4. 在交互等状况使用dispatch一个相应的action,
  5. reducer来响应action,并更新store,[store.subscribe监听函数将会被执行来驱动页面变化]
import { createStore } from 'redux';

/**
 * 这是一个 reducer,形式为 (state, action) => state 的纯函数。
 * 描述了 action 如何把 state 转变成下一个 state。
 *
 * state 的形式取决于你,能够是基本类型、数组、对象、
 * 甚至是 Immutable.js 生成的数据结构。唯一的要点是
 * 当 state 变化时须要返回全新的对象,而不是修改传入的参数。
 *
 * 下面例子使用 `switch` 语句和字符串来作判断,但你能够写帮助类(helper)
 * 根据不一样的约定(如方法映射)来判断,只要适用你的项目便可。
 */
function counter(state = 0, action) {
  switch (action.type) {
  case 'INCREMENT':
    return state + 1;
  case 'DECREMENT':
    return state - 1;
  default:
    return state;
  }
}

// 建立 Redux store 来存放应用的状态。
// API 是 { subscribe, dispatch, getState }。
let store = createStore(counter);

// 能够手动订阅更新,也能够事件绑定到视图层。
store.subscribe(() =>
  console.log(store.getState())
);

// 改变内部 state 唯一方法是 dispatch 一个 action。
// action 能够被序列化,用日记记录和储存下来,后期还能够以回放的方式执行
store.dispatch({ type: 'INCREMENT' });
// 1
store.dispatch({ type: 'INCREMENT' });
// 2
store.dispatch({ type: 'DECREMENT' });
// 1

异步redux

像 redux-thunk 或 redux-promise 这样支持异步的 middleware 都包装了 store 的 dispatch() 方法,以此来让你 dispatch 一些除了 action 之外的其余内容,例如:函数或者 Promise。

redux-react

Redux 官方提供的 React 绑定库。 具备高效且灵活的特性。

结合react来完善了下redux的使用,不须要咱们每次都使用store.subscribe来监听store的变化,提供了新的接口:

<Provider store>
能够在最顶层将store传递至每一个须要store的子组件

connect([mapStateToProps], [mapDispatchToProps], [mergeProps], [options])
能够将一些state映射到某个组件,来驱动组件渲染

总结

react-redux-demo

须要webpack3以上

运行方式:

`npm install`  安装相关依赖
`webpack` 执行webpack来进行打包

在浏览器中打开目录下的/html/pages/home.html文件便可访问结果

➜  react-redux-demo git:(master) tree -I node_modules 
.
├── html
│   └── pages
│       └── home.html
├── package-lock.json
├── package.json
├── readMe.md
├── src
│   ├── dist
│   │   ├── css
│   │   │   └── home.css

│   │   ├── images
│   │   │   └── head.jpeg
│   │   └── js
│   │       └── home.js
│   ├── scripts
│   │   ├── common
│   │   └── pages
│   │       └── home
│   │           ├── actions
│   │           │   ├── data.js
│   │           │   └── index.js
│   │           ├── components
│   │           │   ├── app.js
│   │           │   ├── article
│   │           │   │   └── index.js
│   │           │   └── consults
│   │           │       └── index.js
│   │           ├── index.js
│   │           ├── reducers
│   │           │   ├── data.js
│   │           │   └── index.js
│   │           └── store
│   │               └── index.js
│   └── styles
│       ├── images
│       │   └── home
│       │       └── head.jpeg
│       ├── lib
│       │   └── base.scss
│       ├── module
│       └── pages
│           └── home.scss
└── webpack.config.js
相关文章
相关标签/搜索