资讯专栏INFORMATION COLUMN

webpack-best-practice-最佳实践-部署生产

txgcwm / 1658人阅读

摘要:如果是在生产环境下,则加入插件,执行代码压缩,并且去除。规定了在开发环境下才使用。疑问目前为止,对于多页面项目还是没有找到一个很好的方案去构建自动化。原文可以看我的博客最佳实践部署生产

tip

webpack的入门篇可以看我的这一片博文。
《如何使用webpack—webpack-howto》.

前言

最近一段时间在项目中使用了webpack和React来开发,总之来说也是遇到了许多坑,webpack毕竟还是比较新的技术,而且也很难有一个很好的构建案例来适应所有的项目,总之,在看了许多项目demo和官方文档以及官方推荐的tutorials之后,也算是自己总结出的一套最佳实践吧。

代码

代码可以在我的Github上。
可以戳这里~~。

package.json 命令配置

既然是需要用到的是实际项目的构建,那么必然就要考虑开发环境和生产环境下的配置项了:

// package.json
{
  // ...
  "scripts": {
    "build": "webpack --progress --colors --watch",
    "watch": "webpack-dev-server --hot --progress --colors",
    "dist": "NODE_ENV=production webpack --progress --colors"
  },
  // ...
}

可以在目录下执行

npm run build
npm run watch
npm run dist

解释一下:

build 是在我们开发环境下执行的构建命令;

watch 也是在开发环境下执行,但是加了webpack最强大的功能--搭建静态服务器和热插拔功能(这个在后面介绍;

dist 是项目在要部署到生产环境时打包发布。

dist 里面的NODE_ENV=production是声明了当前执行的环境是production-生产环境

后面跟着几个命令:

--colors 输出的结果带彩色

--progress 输出进度显示

--watch 动态实时监测依赖文件变化并且更新

--hot 是热插拔

--display-error-details 错误的时候显示更多详细错误信息

--display-modules 默认情况下 node_modules 下的模块会被隐藏,加上这个参数可以显示这些被隐藏的模块

-w 动态实时监测依赖文件变化并且更新

-d 提供sorcemap

-p 对打包文件进行压缩

目录结构

现在前端模块化的趋势导致目录结构也发生了很大的改变和争议,这只是我自己用到的一种形式,可以参考。

.
├── app                 #开发目录
|   ├──assets           #存放静态资源
|   |   ├──datas        #存放数据 json 文件
|   |   ├──images       #存放图片资源文件
|   |   └──styles       #存放全局sass变量文件和reset文件
|   ├──lib
|   |   ├──components   #存放数据 模块组件 文件
|   |   |   └──Header
|   |   |       ├──Header.jsx
|   |   |       └──Header.scss
|   |   |       
|   |   └──utils        #存放utils工具函数文件
|   |
|   └──views
|       ├──Index        #入口文件
|       |   ├──Index.html #html文件
|       |   ├──Index.jsx
|       |   └──Index.scss
|       └──Index2
├── dist                #发布目录
├── node_modules        #包文件夹
├── .gitignore     
├── .jshintrc      
├── webpack.config.js   #webpack配置文件
└── package.json

具体可以到Github上看demo。

webpack.config.js 引入包
var webpack = require("webpack");
var path = require("path");
var fs = require("fs");

这个毋庸置疑吧。

判断是否是在当前生产环境

定义函数判断是否是在当前生产环境,这个很重要,一位开发环境和生产环境配置上有一些区别

var isProduction = function () {
  return process.env.NODE_ENV === "production";
};
声明文件夹
// 定义输出文件夹
var outputDir = "./dist";
// 定义开发文件夹
var entryPath = "./app/views";
定义插件
var plugins = [
  new webpack.optimize.CommonsChunkPlugin({
    name: "commons",
    filename: "js/commons.js",
  }),
  new webpack.ProvidePlugin({
    React: "react",
    ReactDOM: "react-dom",
    reqwest: "reqwest",
  }),
];
if( isProduction() ) {
  plugins.push(
    new webpack.optimize.UglifyJsPlugin({
      test: /(.jsx|.js)$/,
      compress: {
        warnings: false
      },
    })
  );
}

CommonsChunkPlugin 插件可以打包所有文件的共用部分生产一个commons.js文件。

ProvidePlugin 插件可以定义一个共用的入口,比如下面加的 React ,他会在每个文件自动require了react,所以你在文件中不需要 require("react"),也可以使用 React。

如果是在生产环境下,则加入插件 UglifyJsPlugin ,执行代码压缩,并且去除 warnings。

自动遍历多文件入口
var entris = fs.readdirSync(entryPath).reduce(function (o, filename) {
    !/./.test(filename) &&
    (o[filename] = "./" + path.join(entryPath, filename, filename + ".jsx"));
    return o;
  }, {}
);

函数会自动遍历开发的入口文件夹下面的文件,然后一一生产入口并且返回一个对象--入口。

如果在这一步不需要多页面多入口

那么可以使用html-webpack-plugin插件,它可以自动为入口生成一个html文件,配置如下:

var HtmlWebpackPlugin = require("html-webpack-plugin");
plugins.push(new HtmlWebpackPlugin({
  title: "index",
  filename: outputDir+"/index.html",  #生成html的位置
  inject: "body",                     #插入script在body标签里
}));

entry 就可以自定义一个入口就够了

config的具体配置
var config = {
  target: "web",
  cache: true,
  entry: entris,
  output: {
    path: outputDir,
    filename: "js/[name].bundle.js",
    publicPath: isProduction()? "http://******" : "http://localhost:3000",
  },
  module: {
    loaders: [
      {
        test: /(.jsx|.js)$/,
        loaders: ["babel?presets[]=es2015&presets[]=react"],
        exclude: /node_modules/
      },
      {
        test: /.scss$/,
        loaders: ["style", "css?root="+__dirname, "resolve-url", "sass"]
      },
      {
        test: /.json$/,
        loader: "json",
      },
      {
        test: /.(jpe?g|png|gif|svg)$/,
        loader: "url?limit=1024&name=img/[name].[ext]"
      },
      {
        test: /.(woff2?|otf|eot|svg|ttf)$/i,
        loader: "url?name=fonts/[name].[ext]"
      },
      {
        test: /.html$/,
        loader: "file?name=views/[name].[ext]"
      },
    ]
  },
  plugins: plugins,
  resolve: {
    extensions: ["", ".js", "jsx"],
  },
  devtool: isProduction()?null:"source-map",
};

这里来一一说明:

对于output

path和filename都不用多说了,path是生成文件的存放目录,filename是文件名,当然可以在前面加上目录位置。
这里提醒一下,filename 的相对路径就是 path了,并且下面 静态文件生成的filename也是相对于这里的path的,比如 image 和 html。
publicPath 的话是打包的时候生成的文件链接,比如 图片 资源,
如果是在生产环境当然是用服务器地址,如果是开发环境就是用本地静态服务器的地址。

module loaders 打包加载的处理器

可以不用夹 loader了 比如 原来 url-loader 现在 url

js/jsx
{
  test: /(.jsx|.js)$/,
  loaders: ["babel?presets[]=es2015&presets[]=react"],
  exclude: /node_modules/
},

对于js文件和jsx文件用了babel来处理,这里注意一下,最新版本的babel吧es2015和react的处理分开了,所有要这么写。

处理scss文件
{
  test: /.scss$/,
  loaders: ["style", "css?root="+__dirname, "resolve-url", "sass"]
},

这里用了sass、css、style的loader这不用多说了。
那么root和resolve-url是怎么回事呢,root是定义了scss文件里面声明的url地址是相对于根目录的,然后resolve-url回去相对解析这个路径,而不用require去获取,比如

background: url("./assets/images/webpack.png");

这样就可以加载到./assets/images/webpack.png这个文件,而不用使用相对路径和require

处理json文件
{
  test: /.json$/,
  loader: "json",
},

对于json文件,可以自动请求该模块并且打包。

处理 图片 字体 资源文件
{
  test: /.(jpe?g|png|gif|svg)$/,
  loader: "url?limit=1024&name=img/[name].[ext]"
},
{
  test: /.(woff2?|otf|eot|svg|ttf)$/i,
  loader: "url?name=fonts/[name].[ext]"
},

这里使用了 url 这个loader,但是url依赖 file-loader,它是对file-loader的二次封装。
在请求图片的时候如果文件大小小于 1024k ,使用内联 base64 URLs,否则会自动导入到name所声明的目录,这里是相对之前声明的 outputDir 路径。
字体资源也是一样。

处理html文件
{
  test: /.html$/,
  loader: "file?name=views/[name].[ext]"
},

在多页面的项目中需要,可以自动吧html文件导入到指定的生产文件夹下。

resolve
resolve: {
  extensions: ["", ".js", "jsx"],
},

是可以忽略的文件后缀名,比如可以直接require("Header");而不用加.jsx。

devtool
devtool: isProduction()?null:"source-map",

规定了在开发环境下才使用 source-map。

疑问

目前为止,对于多页面项目还是没有找到一个很好的方案去构建自动化。

原文可以看我的博客 webpack-best-practice-最佳实践-部署生产;

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/78249.html

相关文章

  • 谈谈 react-router

    摘要:谈谈最近使用的来开发项目,感觉确实是爽的飞起,然而总感觉还是少了点什么。注意当前版本依赖的是请不要安装最新版。同样的也有这个方法表示在离开路由前执行。会深度优先遍历整个理由配置来寻找一个与给定的相匹配的路由。配置是建立在之上的。 谈谈 最近使用的 React + webpack 来开发项目,感觉确实是爽的飞起,然而总感觉还是少了点什么。对,是多页面,每次请求页面还要后端路由给你?多不爽...

    MASAILA 评论0 收藏0
  • 数据中心监控最佳实践简化软件选择

    摘要:不同组织的专业人员将对网络监控软件有不同的需求。网络监控软件必须有效地收集有关总消耗带宽传输数据包数量和数据包错误发生率的信息。这可以预防维护性能瓶颈和维护数据中心监控最佳实践。衡量指标是保持数据中心正常运行的必要条件。使用监控软件和最佳实践,管理人员可以简化工作流程,并获得可用的数据。监控功能是数据中心管理的关键部分,尤其是IT管理人员每天负责的组件数量。监控软件提供的工具可以简化任务,并...

    william 评论0 收藏0
  • 赢得Docker挑战最佳实践

    摘要:因此,将应用程序部署到生产需要数周或数月。它将改变应用程序开发过程,但某些挑战必须克服从而使得企业获得最大好处。平台将促进的发展,并且帮助其履行自己的承诺。 showImg(https://segmentfault.com/img/bVpNBt); 难怪Docker正在迅速发展。Docker,一个开源项目。仅仅两年,Docker价值近10亿美元,最近获得了9500万美元的资金。令人激动...

    fou7 评论0 收藏0
  • Kubernetes 落地案例|在线课程平台 Descomplica 使用 Kubernetes 5

    摘要:使用这个工具是由的几个人创建的。它最厉害的地方在于,在下,使用,这对于我们来说有利无弊。在我们的这个案例中,我们添加集群层面的日志记录,摄取应用程序日志到,用和进行集群监控,基于的授权认证,以及一些其它的事情。 在过去一年内,Descomplica 计划往核心组件服务化的方向发展,我们一开始使用 Elastic Beanstalk 将这些服务编排到 AWS。 那时候来说,这个决定是明智...

    hzc 评论0 收藏0
  • Kubernetes部署最佳安全实践

    摘要:将成安全评估如漏洞扫描加入持续集成中,使其成为构建流程的一部分。持续集成应确保只使用审查通过的代码来构建镜像。我们推荐这篇文章中提到的安全实践,将的灵活配置能力加入到持续集成中,自动将安全性无缝融合到整个流程中。 编者按:本文是由 Aqua Security 的Amir Jerbi 和Michael Cherny 所写,基于他们从本地和云端上收集到的实际数据,描述了Kubernetes...

    Rocture 评论0 收藏0

发表评论

0条评论

txgcwm

|高级讲师

TA的文章

阅读更多
最新活动
阅读需要支付1元查看
<