spm to atool-build

spm.output

spm.output

  1. {
  2. "output": [
  3. "./src/index.js",
  4. "./src/indexb.js",
  5. "./src/afwealth/*.js"
  6. "./src/index.css",
  7. "./src/x.css",
  8. "./index.html",
  9. "./fav.icon",
  10. "./src/img/test.png"
  11. ]
  12. }

spm 中,在 package.jsonoutput 内可以指定具体需要打包的条目。

atool-build 存在类似配置,但是不能完全实现这样操作。

类似功能在 atool-build 中叫 entry

所以一份 atool 中的配置是这样的

package.json

  1. {
  2. "entry": {
  3. "index" : "./src/index.js",
  4. "indexb" : "./src/indexb.js"
  5. }
  6. }

注意

atoolentry 默认只支持 js. 同时 entry 中的 key 对应最终打包出来的文件中会含有 key.js , common.js , key.css, common.css (如果没有样式文件则没有 css 文件)

所以如上 entry 最终可能打包出来的文件是 index.js , indexb.js common.js , index.css , indexb.css , common.css

案例

  • 如何实现通配符 "./src/afwealth/*.js"

    首先你需要了解下 webpack.config.js

    我们可以通过 webpack.config.jsatool-build 内置的 webpack 配置进一步进行处理(添加一些 loaderplugin 等),得到项目实际需要的效果。webpack.config.js 里有一个函数,会将内置的 webpack 配置对象作为参数,而这个函数的返回值会作为新的 webpack 配置对象。所以,我们只需要改变这个对象就可以完成个性化配置。

    所以方案便可以是利用 node 读取某个文件夹下的所有文件名,并通过正则筛选出最终需要的 .js 文件,并最后 pushentry 这个数组中。

  • 如何实现样式文件的导出 "./src/x.css"

    • 如果该 x.css 已经被某脚本如 xx.js 中有引用到,那么不必专门进行设置导出,默认配置中会生成与脚本同名的样式文件即 xx.css 该样式文件包含了所有的脚本所依赖的样式文件。
    • 如果该 x.css 不得不进行导出,可以有的方案是,新建一个脚本文件,如 x.js,并在 entry 中进行如下的设置
      1. {
      2. "entry": {
      3. "xx" : "path/to/xx.js",
      4. "x" : ["path/to/x.js"]
      5. }
      6. }
      为什么是 [] 呢 ?不设置 Mutiple Entry 会得到如下报错 Module not found: Error: a dependency to an entry point is not allowed

    警告 虽然在 entry 中也可以直接设置 css 或者 less 但是实际操作中 webpack 还是会把他先当成一个脚本再抽取样式,所以此时构建目录中会多一个和样式文件同名的脚本,并不推荐直接在 entry 中写样式.

  • 如何实现 html 的导出比如 "./src/index.html" ? 在 atool-build 中默认不支持 html, 目前正在考虑是否需要集成,详见issue

    • 如果只是想完成简单的拷贝功能

      1. module.exports = function(webpackConfig) {
      2. webpackConfig.module.loaders.push({ test: /\.html$/, loader: 'file?name=[name].[ext]' })
      3. return webpackConfig;
      4. };

      从此边可以在 对应的 脚本中 require('path/to/html')

    • 如果想完成更加复杂的功能,比如 minify or html tpl 则可以考虑使用其他社区更加强大的 loader 或者 plugin 。比如 html-loader, html-webpack-plugin, plugin 使用可以参考如下 添加一个plugin


spm.global

spm.global

atool-build 中需要自定义 webpack.config.js 来实现

  1. module.exports = function(webpackConfig) {
  2. webpackConfig.externals = {
  3. jquery: "jQuery",
  4. };
  5. return webpackConfig;
  6. };

关于更多 externals 请查看 webpack#externals


spm.node

spm.node

配置引入 node 相关的补丁。

atool-build 中需要自定义 webpack.config.js 来实现

举例:如果在你的业务代码中也需要 node 中的 url 可以通过如下实现

  1. module.exports = function(webpackConfig) {
  2. webpackConfig.node = {
  3. url: true,
  4. };
  5. return webpackConfig;
  6. };

构建时会把适配于浏览器的 url 也打包在内.

node 的默认配置为

  1. // Default:
  2. {
  3. console: false,
  4. global: true,
  5. process: true,
  6. Buffer: true,
  7. __filename: "mock",
  8. __dirname: "mock",
  9. setImmediate: true
  10. }

关于更多 node 请查看 webpack#externals

另外参考代码有 Profill


spm.vendor

spm.vendor

vendorwebpack 中对应的功能点是 CODE SPLITTING 也可以在此查看 webpack 对其的一些说明 参考链接

功能点:代码分割,需要配合插件 CommonsChunkPlugin

举例来说

现在我们在业务中有两个页面,pageApageB

  • pageA
    • jquery
    • util1
  • pageB
    • underscore
    • util1
    • util2

现在我们需要抽取 jqueryunderscore 。 此时基于 atool-build 我们需要怎么做呢?

  1. 第一步在 package.jsonentry 予以说明

    1. "entry": {
    2. "pageA": "path/to/pageAEntry",
    3. "pageB": "path/to/pageBEntry",
    4. "vendor": ["jquery", "undersocre"]
    5. }
  2. 第二步由于 atool-build 中内置了CommonsChunkPlugin 并且也有默认的配置在此我们需要去覆盖它。

    1. var webpack = require('atool-build/lib/webpack');
    2. module.exports = function(webpackConfig) {
    3. webpackConfig.plugins.some(function(plugin, i){
    4. if(plugin instanceof webpack.optimize.CommonsChunkPlugin) {
    5. webpackConfig.plugins.splice(i, 1, new webpack.optimize.CommonsChunkPlugin('vendor', 'vendor.bundle.js'));
    6. return true;
    7. }
    8. });
    9. return webpackConfig;
    10. };

那么最后构建出来的文件中会有 vendor.bundle.js 其中代码中包含了 webpack runtime, jqueryunderscore 。 并且最后在业务项目中使用时,需要使用如下这个方式,以 pageA 为例

  1. <script src="path/to/vendor.bundle.js"></script>
  2. <script src="path/to/pageA.js"></script>

spm.common

spm.common

如上条所述,在 atool-build 中已经内置了 common 的功能,默认开启.

common 是自主性的动作作为用户不需要配置哪些是公共 chunk 。而 vendor 是被动性的。

最后我们在页面上引用的时候需要如下方式:

  1. <script src="path/to/common.js"></script>
  2. <script src="path/to/your/entry.js"></script>
  • 如果你并不想启用 common 该如何使用呢? 添加 webpack.config.js

    1. var webpack = require('atool-build/lib/webpack');
    2. module.exports = function(webpackConfig) {
    3. webpackConfig.plugins.some(function(plugin, i){
    4. if(plugin instanceof webpack.optimize.CommonsChunkPlugin) {
    5. webpackConfig.plugins.splice(i, 1);
    6. return true;
    7. }
    8. });
    9. return webpackConfig;
    10. };
  • 如果你同时想拥有 vendorcommon 。如 vendor 示例中所示,在 entry 中添加 vendor 配置,再添加 webpack.config.js

    1. var webpack = require('atool-build/lib/webpack');
    2. module.exports = function(webpackConfig) {
    3. webpackConfig.plugins.some(function(plugin, i){
    4. if(plugin instanceof webpack.optimize.CommonsChunkPlugin) {
    5. webpackConfig.plugins.splice(i, 1, new webpack.optimize.CommonsChunkPlugin({
    6. names: ["common", "vendor"],
    7. minChunks: 2
    8. }));
    9. return true;
    10. }
    11. });
    12. return webpackConfig;
    13. };

    更多 commonschunkplugin 参数 参考示例


spm.base64

spm.base64

atool-build 中已经内置了对 base64 的支持, 更确切说是对 data url, 而完成该工作的正是 webpackurl-loader

相关配置可以在源码中查看 atool-build 中关于关于 url-loader 配置

配置默认对 10kb 的文件都会做 data url 的处理。并且把相关文件路径提取到根路径,文件名 hash 化。

  • 如何配置默认对 20kb 的图片文件都会做 data url 的处理? 书写 webpack.config.js 覆盖 atool-build 中处理图片的 loader 配置

    1. webpackConfig.module.loaders.some(function(loader) {
    2. if (loader.loader === 'url?limit=10000') {
    3. loader.loader = 'url?limit=20000';
    4. return true;
    5. }
    6. });
  • 如何除去对图片文件的 data url 的处理? 这边就牵扯到如何使用 loader 了。查看 url-loader 的文档,便可以看到如下说明

    The url loader works like the file loader, but can return a Data Url if the file is smaller than a limit. If the file is greater than the limit the file-loader is used and all query parameters are passed to it.

    1. webpackConfig.module.loaders.some(function(loader) {
    2. if (loader.loader === 'url?limit=10000') {
    3. loader.loader = 'file?name=[name].[ext]'
    4. return true;
    5. }
    6. });
  • 如何不对图片的文件名hash化,并保留原有路径?

    1. webpackConfig.module.loaders.some(function(loader) {
    2. if (loader.loader === 'url?limit=10000') {
    3. loader.loader = 'file?name=[path][name].[ext]'
    4. return true;
    5. }
    6. });

    更多参数请参考 [file-loader](https://github.com/webpack/file-loader)


spm.babel

spm.babel

atool-build 中我们对 jsjsx 文件的配置如下

  1. {
  2. presets: ['es2015', 'react', 'stage-0'],
  3. plugins: ['add-module-exports', 'typecheck'],
  4. }

更多的配置详见 babel.options

在这边目前遇到的业务中可能出现的问题是: 在 es2015 规范中需要对脚本文件启用严格模式,即在脚本代码前默认添加 "use strict", 但是这些一些老的业务系统里面可能行不通,由于个别用法会导致出错。如何避免出现这个问题呢?

  1. webpackConfig.module.loaders.some(function(loader) {
  2. var needFixBabelOptionCount = 2;
  3. if (loader.loader === 'babel') {
  4. needFixBabelOptionCount --;
  5. loader.query.presets = ['es2015-without-strict', 'react', 'stage-0'];
  6. if (needFixBabelOptionCount == 0) {
  7. return true;
  8. };
  9. }
  10. });

spm.uglify

spm.uglify

atool-build 内置了 UglifyJsPlugin

  1. new webpack.optimize.UglifyJsPlugin({
  2. output: {
  3. ascii_only: true,
  4. },
  5. compress: {
  6. warnings: false,
  7. },
  8. })

目前暂时没有方式能够覆盖这个配置,但是后续应该会开放参数,这会在之后的变更中予以更新,查看 issue 以查看最新进展

在使用 atool-build 时可以通过添加 --no-compress 的方式对源码不进行压缩。 /to/your/atool-build --no-compress


spm.autoprefixer

spm.autoprefixer

atool-build 中已经内置了对 autoprefixer

  • 如何给 autoprefixer 添加相关配置呢? 目前暂时没有直接传参的方式,但是还是有办法尝试覆盖,在 webpack.config.js 中单独引入 autoprefixer

    1. var webpack = require('atool-build/lib/webpack');
    2. var autoprefixer = require('autoprefixer');
    3. module.exports = function(webpackConfig) {
    4. webpackConfig.postcss.some(function (plugin,i) {
    5. if (plugin.postcss.postcssPlugin === 'autoprefixer') {
    6. webpackConfig.postcss.splice(i, 1, autoprefixer({ browsers: ['last 2 versions'] }));
    7. return true;
    8. }
    9. });
    10. return webpackConfig;
    11. };

spm.dest

spm.dest

atool-build 中,我们可以使用构建参数来指定需要构建到的目录 -o

/to/your/atool-build -o ./www

当然我们也可以使用 webpack.config.js 来达到设置构建目录的目的, 使用 assign 是我只想要替换 output.path

  1. var webpack = require('atool-build/lib/webpack');
  2. var assign = require('object-assign');
  3. module.exports = function(webpackConfig) {
  4. var preOutput = webpackConfig.output;
  5. webpackConfig.output = assign(preOutput, {
  6. path: join(process.cwd(), './www/'),
  7. });
  8. return webpackConfig;
  9. };

更多 output 参数


spm.hash

spm.hash

atool-build 中,我们可以使用构建参数来指定需要构建到的目录 —hash

/to/your/atool-build -o ./www --hash

在使用 hash 构建后, 在构建文件夹中生成映射表 map.json

诸如

  1. {
  2. "spm2atool/common.js": "spm2atool/common-8a88e1a952820cb5d6f0.js",
  3. "spm2atool/c.js": "spm2atool/c-e25ee7b379a3fc0b08bc.js",
  4. "spm2atool/vendor.js": "spm2atool/vendor-ed4ac329980b6a5dca78.js",
  5. "spm2atool/c.css": "spm2atool/c-e25ee7b379a3fc0b08bc.css"
  6. }

spm.extractCSS

spm.extractCSS

webpack 中对应的是插件 ExtractTextPlugin atool-build 中我们对其进行了内置,构建工具主动会对 cssless 文件默认会抽取成独立的文件。

如果有些组件需要内置样式,可能并不需要该功能。那么把如上 csslessloader 进行替换。这边就不在阐述,可以参考如上案例。


spm.library 相关

spm.library spm.libraryTarget spm.umd

这三种对应在 webpack 中分别是:

  • library 如果配置了,则作为类库输出,library 为类库名
  • libraryTarget 配置输出格式,默认 var, 可选 var, this, commonjs, commonjs2, amd, umd
  • umd 配置输出格式为 umd,并指定类库名。

案例

如何配置 library, libraryTarget 呢?

  1. var assign = require('object-assign');
  2. module.exports = function(webpackConfig) {
  3. var preOutput = webpackConfig.output;
  4. webpackConfig.output = assign(preOutput, {
  5. path: join(process.cwd(), './www/'),
  6. library: 'pigcan',
  7. libraryTarget: 'this'
  8. });
  9. return webpackConfig;
  10. };

spm.loader

spm.loader

可以在 webpack 官网 很多的 loader 自行挑选自己所需的吧.

案例: 需要压缩 html-minify 这个loader

  1. 第一步安装 html-minify 这个 loadernpm install html-minify-loader --save-dev
  2. 第二步建立 webpack.config.js
  3. 第三步编辑如上配置文件

    1. var html-minify =
    2. module.exports = function(webpackConfig) {
    3. webpackConfig.module.loaders.push({
    4. test: /\.html$/,
    5. name: "mandrillTemplates",
    6. loader: 'raw!html-minify'
    7. });
    8. return webpackConfig;
    9. }

spm.define

spm.define

atool-build 中 已经内置了 DefinePlugin

相关讨论 issue 最新进展

  1. var webpack = require('atool-build/lib/webpack');
  2. module.exports = function(webpackConfig) {
  3. var define = {
  4. "default": {
  5. "DATAHOST": "http://localhost",
  6. "DEBUG": true
  7. },
  8. "test": {
  9. "DATAHOST": "http://x.sit.hostname.net",
  10. "DEBUG": true
  11. },
  12. "prod": {
  13. "DATAHOST": "http://x.hostname.com",
  14. "DEBUG": false
  15. },
  16. "string": "ooxx"
  17. }
  18. var definePluginOptionKey = define[process.env.NODE_ENV] ? process.env.NODE_ENV : define['default'] ? 'default' : '';
  19. if(definePluginOptionKey){
  20. var definePluginOption;
  21. var defineContent = define[definePluginOptionKey];
  22. if (typeof defineContent === 'object') {
  23. for (var i in defineContent) {
  24. (typeof(defineContent[i]) === 'string' || typeof(defineContent[i] === 'object')) && (defineContent[i] = JSON.stringify(defineContent[i]));
  25. }
  26. }
  27. webpackConfig.plugins.push(
  28. new webpack.DefinePlugin(defineContent)
  29. )
  30. }
  31. return webpackConfig;
  32. };

这样我们便可以使用 node 的环境变量来达到自定义构建的效果 即:

NODE_ENV=prod npm run build NODE_ENV=test npm run build npm run build

查看更多关于 DefinePlugin