使用 webpack2 和 NPM Scripts 进行 JavaScript 组件开发

xunjw 8年前
   <p>最近 webpack 成为非常流行的打包工具,很多项目都在使用它。在我们进行 <strong>JavaScript 独立组件</strong> 开发的时候,如果我们想要使用语言新特性,又想发布的时候产出兼容性好的代码,那么使用 webpack 就能够很大程度上帮助我们实现这一目标。</p>    <p>现在让我们来看看究竟该怎么做吧。</p>    <h2>搭建一个简易环境</h2>    <p>首先,第一步是初始化和安装一些必要的依赖,搭建一个简易的开发和调试环境:</p>    <pre>  <code class="language-javascript"># 初始化 package.json  npm init -i  # 安装 http-server  npm install http-server  # 安装 webpack   npm install webpack webpack-dev-server --save-dev  # 安装 babel 和 babel 插件,如果不想使用 babel 编译 ES6+,可以跳过这一步  npm install babel-loader babel-core babel-preset-env --save-dev</code></pre>    <p>有了这个基础环境之后,我们来配置一份 webpack.config.js</p>    <h2>配置 webpack</h2>    <p>我们在项目目录里添加 webpack.config.js</p>    <pre>  <code class="language-javascript">module.exports = function(env = {}){      const webpack     = require('webpack'),          path        = require('path'),          fs          = require('fs'),          packageConf = JSON.parse(fs.readFileSync('package.json', 'utf-8'));      let name      = packageConf.name,        version   = packageConf.version,        library   = name.replace(/^(\w)/, m => m.toUpperCase()),        proxyPort = 8081,        plugins   = [],        loaders   = [];      if(env.production){      name += `-${version}.min`;      //compress js in production environment      plugins.push(        new webpack.optimize.UglifyJsPlugin({          compress: {            warnings: false,            drop_console: false,           }        })      );    }      if(fs.existsSync('./.babelrc')){      //use babel      let babelConf = JSON.parse(fs.readFileSync('.babelrc'));      loaders.push({        test: /\.js$/,        exclude: /(node_modules|bower_components)/,        loader: 'babel-loader',        query: babelConf      });    }      return {      entry: './lib/app.js',      output: {        filename: `${name}.js`,        path: path.resolve(__dirname, 'dist'),        publicPath: '/static/js/',        library: `${library}`,        libraryTarget: 'umd'      },        plugins: plugins,        module: {        loaders: loaders      },        devServer: {        proxy: {          "*": `http://127.0.0.1:${proxyPort}`,        }      }    };  }</code></pre>    <p>代码比较长,但不复杂,这里我分别解释一下各部分的作用:</p>    <h3>生产环境和开发环境</h3>    <p>首先我们从 package.json 里面取出一些信息,包括模块名和版本号,我们依赖它们来生成对应的 umd 模块的 library、输出的文件名以及版本号。</p>    <p>在这里我们规定在开发环境时输出 模块名.js ,在生产环境发布时输出 模块名-版本号.min.js 。</p>    <p>在 webpack2 里,我们可以通过 env.production 获取命令行参数 --production ,从而区别是开发环境还是生产环境。</p>    <pre>  <code class="language-javascript">if(env.production){      name += `-${version}.min`;      //compress js in production environment      plugins.push(        new webpack.optimize.UglifyJsPlugin({          compress: {            warnings: false,            drop_console: false,           }        })      );    }</code></pre>    <p>在生产环境中,我们不仅改变输出的文件名,还配置 UglifyJsPlugin 来压缩脚本。</p>    <h3>使用 babel 编译 ES6</h3>    <p>如果脚本用到 ES6,我们希望用 babel 编译的话,还需要加载 babel-loader 来进行编译。我们采用 babel 的默认配置 .babelrc ,在项目目录里添加 .babelrc:</p>    <pre>  <code class="language-javascript">{    "presets": ["env"],    "plugins": ["transform-runtime"]  }</code></pre>    <p>然后我们在 webpack.config.json 里根据配置来添加 loader:</p>    <pre>  <code class="language-javascript">if(fs.existsSync('./.babelrc')){      //use babel      let babelConf = JSON.parse(fs.readFileSync('.babelrc'));      loaders.push({        test: /\.js$/,        exclude: /(node_modules|bower_components)/,        loader: 'babel-loader',        query: babelConf      });    }</code></pre>    <h3>配置开发调试的 webpack-dev-server</h3>    <p>最后,为了在开发环境里调试,我们还需要配置 webpack-dev-server:</p>    <pre>  <code class="language-javascript">devServer: {        proxy: {          "*": `http://127.0.0.1:${proxyPort}`,        }      }</code></pre>    <p>webpack-dev-server 是一个代理,我们之前安装了 http-server,我们用 webpack-dev-server 来代理它,所以开发时我们让 http-server 运行在 8081 端口:</p>    <pre>  <code class="language-javascript">webpack-dev-server --quiet & http-server -p 8081 -c-1</code></pre>    <h2>创建 NPM Scripts</h2>    <p>配置好了 webpack,创建 NPM Scripts 是个非常简单的过程:</p>    <pre>  <code class="language-javascript">"scripts": {      [...]      "start": "webpack-dev-server --quiet & http-server -c-1 -p 8081",      "build-release": "webpack --env.production"    },</code></pre>    <p>我们在 package.json 里添加两个脚本,这样我们就可以使用 npm start 来启动开发环境,使用 npm run build-release 来发布到生产环境了。</p>    <h2>开始项目开发</h2>    <p>接下来我们创建 lib/app.js:</p>    <pre>  <code class="language-javascript">module.exports = require('./demo');</code></pre>    <p>然后创建 lib/demo.js:</p>    <pre>  <code class="language-javascript">module.exports = class Demo{    async test(){      return new Promise((resolve) => {        setTimeout(resolve, 1000)      });    }  }</code></pre>    <p>创建 examples/index.html:</p>    <pre>  <code class="language-javascript"><!DOCTYPE html>  <html lang="en">  <head>    <meta charset="UTF-8">    <title>Demo</title>  </head>  <body>    <h1>Hello</h1>    <script src="/static/js/demo.js"></script>    <script>      var d = new Demo();      d.test().then(function(){        console.log('test done!');      });    </script>  </body>  </html></code></pre>    <p>运行 npm start ,访问 <a href="/misc/goto?guid=4959740889358800841" rel="nofollow,noindex">http://localhost:8080/examples/index.html</a></p>    <p>打开控制台,1秒后就能看到输出 test done 。</p>    <h3>构建和发布</h3>    <p>接下来,我们可以停止开发服务器,运行 npm run build-release 。如果你的 package.json 里的版本号是 1.0.0,那么它将在 dist 目录下生成 demo-1.1.0.min.js。这是一个 umd 的包,所以你可以在浏览器中使用 amd/cmd 库加载或者直接在 script 标签中引入和使用。</p>    <h2>总结</h2>    <p>我们使用 webpack 搭建了一个简单的组件开发环境,这样我们可以简单地开始我们的 JS 组件开发,使用新的语言规范,然后通过 webpack-dev-server 代理 http-server 进行调试,通过 webpack --env.production 进行发布。我们还可以将它们与 NPM Scripts 集成,这样我们的组件开发就非常方便了。</p>    <p> </p>    <p> </p>    <p>来自:https://www.h5jun.com/post/using-webpack2-and-npm-scripts.html</p>    <p> </p>