在 APICloud 项目中使用 Webpack

发布时间:2019-08-20 发布网站:脚本宝典
脚本宝典收集整理的这篇文章主要介绍了在 APICloud 项目中使用 Webpack脚本宝典觉得挺不错的,现在分享给大家,也给大家做个参考。

前言

最近项目所需,所以开始学习并且使用 APICloud 此款 hybrid APP 开发框架。粗略的看了下文档和部分 Demo 后,已经对 APICloud 开发有一定基础的了解。在这种过程令我有一点疑惑,APicloud 的开发流程和普通的 Web APP 开发其实是很相似的,但是却没有对目前主流的构建工具有先关的教程。我发现虽然官方提供了一个 apicloud-polyfill 的功能,但是只是为了解决在项目中使用 ES6 的问题,而且整个 demo 的开发体验并不好,每次修改代码需要不停的构建在增量更新。随着项目的复杂起来,以及对一些前端新特性的依赖,所以我打算自己动手弄一个适合 APICloud 使用的 Webpack 模板。

项目结构

APICloud 的开发模式其实就是以前的使用 jQuery 的 MPA 开发一样,而且官方不推荐使用 SPA 的开发模式。

|- dist
|- lanuch
|- src
    |- pages
        |- Foo
            |- index.js
            |- index.htML
    |- image
    |- css
    |- scripts
    |- index.js
    |- index.html
|- package.json
|- config.XMl
|- webpack.config.json
|- .babelrc
|- .gitignore
|- .syncignore
|- index.html

上面是我个人对 APICloud 项目的文件夹分类。所有的码都存放在 src 文件夹内,Webpack 打包的主要目录也是 src。

这里规定了每一个单独的 HTML 页面都是需要一个 JavaScript 的入口文件,这也是为了使用 Webpack 进行多页面打包的基础。

Webapck 基础配置文件

在设定好目录结构之后,我们需要开始编写 Webpack 的 config 文件,配置相对来首都比较简单,所以我们就写在一个文件内既可。

webpack.config.js

const path = require('path')
const webpack = require('webpack')
const HtmlWebpackPlugin = require('html-webpack-plugin')
const HtmlWebpackInlineSourcePlugin = require('html-webpack-inline-source-plugin')
const glob = require('glob')

const paths = {}
const configs = []
const setPath = (item, type) => {
  const dirname = path.dirname(item)
  
  if (paths[dirname]) {
    paths[dirname][type] = item
  } else {
    paths[dirname] = {
      [type]: item
    }
  }
}

glob.sync('./src/**/*.js', { ignore: './src/script/*.js' }).forEach(item => setPath(item, 'script'))
glob.sync('./src/**/*.html').forEach(item => setPath(item, 'html'))

Object.keys(paths).forEach(key => {
  const distName = key.replace('src', 'dist')

  configs.push({
    entry: paths[key].script,
    output: {
      filename: '[name].bundle.js',
      path: path.resolve(__dirname, distName)
    },
    devtool: process.env.NODE_ENV === 'production' ? 'inline-source-map' : '#source-map',
    devServer: {
      host: '0.0.0.0',
      port: 8080,
      historyApiFallback: false,
      noInfo: true
    },
    resolve: {
      extensions: ['.js', '.vue'],
      alias: {
        '@': path.resolve(__dirname, 'src'),
        'vue$': 'vue/dist/vue.esm.js'
      }
    },
    module: {
      rules: [
        {
          test: /.js$/,
          exclude: /(node_modules|bower_components)/,
          loader: 'babel-loader'
        },
        {
          test: /.css$/,
          use: [
            'style-loader',
            'css-loader'
          ]
        },
        {
          test: /.(png|svg|jpg|gif)$/,
          use: [
            'file-loader'
          ]
        },
        {
          test: /.(woff|woff2|eot|ttf|otf)$/,
          use: [
            'file-loader'
          ]
        }
      ]
    },
    plugins: [].concat(
      [
        new HtmlWebpackPlugin({
          inlineSource: '.(js|css)$',
          template: paths[key].html
        })
      ],
      process.env.NODE_ENV === 'production' ? [
        new webpack.DefinePlugin({
          'process.env': {
            NODE_ENV: '"production"'
          }
        }),
        new webpack.optimize.UglifyJsPlugin({
          sourceMap: true,
          compress: {
            warnings: false
          }
        }),
        new webpack.LoaderOptionsPlugin({
          minimize: true
        }),
        new HtmlWebpackInlineSourcePlugin(),
      ] : []
    )
  })
})

module.exports = configs

package.json

{
  "name": "webpack-demo",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "build": "cross-env NODE_ENV=production webpack --progress ",
    "dev": "cross-env NODE_ENV=development webpack-dev-server --open"
  },
  "author": "",
  "license": "ISC",
  "devDependencies": {
    "babel-core": "^6.25.0",
    "babel-loader": "^7.1.1",
    "babel-preset-env": "^1.6.0",
    "cross-env": "^5.0.5",
    "css-loader": "^0.28.4",
    "file-loader": "^0.11.2",
    "glob": "^7.1.2",
    "html-webpack-inline-source-plugin": "0.0.9",
    "html-webpack-plugin": "^2.30.1",
    "style-loader": "^0.18.2",
    "webpack": "^3.5.4",
    "webpack-dev-server": "^2.7.1"
  },
  "dependencies": {
    "vue": "^2.4.2"
  }
}

在 Webpack 中我们导出的是一个 config 数组,通过扫描 src 文件下的 JavaScript 和 HTML 文件,获取它们的 path 信息,为每一个 JavaScript 进行打包。此外我们可能还需要忽略一些 JavaScript 文件。

在生产环境的构建下,我配置了将 css 和 JavaScript 都插入了 html 文件中,这又是官方的一种提倡做法。

估计上面的配置好后,设置两个 npm script 命令,方便开发使用:

  • npm run dev:启动本地开发服务器
  • npm run build:编译项目,输出到 dist 目录下。
  • @H_304_402@

    修改入口地址

    在 APICloud 项目里,我们在根目录有一个 index.html 文件,这是一个入口文件,我们可以通过修改 config.xml 来修改入口文件。一般来说都是通过 openFrame 或者 openWin 来嵌入或者打开一个页面,在我们的本地开发环境下,我们通过 Webpack 启动了一个本地服务器进行调试,所以我们也需要将地址从目录的相对地址改为一段 url。例如:

    <script type="text/javascript">
      apiready = function () {
        api.openFrame({
          name: 'main',
          // url: 'dist/index.html',
          url: 'http://<你的本机 ip>:[端口号]',
          rect: {
            x: 0,
            y: 45,
            w: 'auto',
            h: 'auto'
          }
        })
      }
    </script>

    如果需要编译项目的话,入口文件也需要修改成相对路径。这是一个麻烦的点,目前还没什么好办法解决。

    集成 ESlint

    目标,在开发和编译过程中 Webpack 能够使用 eslint 检查代码,出现错误不通过,使用 aribnb 的 JavaScript 风格编程。

    webpack.config.json

    ...
    configs.push({
        ...
        module: {
            rules: [
                {
                  enforce: "pre",
                  test: /.js$/,
                  exclude: /(node_modules|bower_components)/,
                  loader: "eslint-loader",
                },
                ...
            ]
        }
    })
    ...

    package.json

    {
        ...
        devDependencies: {
            ...
            "eslint": "^4.4.1",
            "eslint-config-airbnb-base": "^11.3.1",
            "eslint-loader": "^1.9.0",
            "eslint-plugin-html": "^3.2.0",
            "eslint-plugin-import": "^2.7.0",
            ...
        }
        ...
    }

    .eslintrc

    {
      "extends": "airbnb-base",
      "plugins": [
        "html"
      ]
    }

    .eslintignore

    node_modules
    dist
    
    *.css

    Airbnb JavaScript Style Guide

    结语

    这次对 APICloud 集成 Webpack 尝试,结果还算可。但是个人对 APICloud 的开发还是非常的不满意的,对于 React Native 来说:没有热更新、在 APP loader 下调试不能使用 Chrome developer tool等。看网上对这个框架的评价,也是处于一个较低的水平。只能通过这次项目的开发再深入了解的它们的利弊了。

    项目地址:APICloud-Webpack-Demo

    脚本宝典总结

    以上是脚本宝典为你收集整理的在 APICloud 项目中使用 Webpack全部内容,希望文章能够帮你解决在 APICloud 项目中使用 Webpack所遇到的问题。

    如果觉得脚本宝典网站内容还不错,欢迎将脚本宝典推荐好友。

    本图文内容来源于网友网络收集整理提供,作为学习参考使用,版权属于原作者。
    如您有任何意见或建议可联系处理。小编QQ:384754419,请注明来意。