コンテンツにスキップ

Browserifyチートシート

Browserify - Browser-side require()

Browserifyを使用すると、依存関係をすべてバンドルすることで、ブラウザで require('modules') を使用できます。Node.jsと同じモジュールシステムを使用し、npmモジュールをブラウザで使用し、CommonJSモジュールでコードを整理できます。

(This section appears to be empty in the original text, so no translation is needed)

目次

Would you like me to continue translating the remaining sections? Please confirm, and I’ll proceed with the translations.```bash

Install Browserify globally

npm install -g browserify

Verify installation

browserify —version


### Local Installation (Recommended)
```bash
# Initialize npm project
npm init -y

# Install Browserify locally
npm install --save-dev browserify

# Install common transforms
npm install --save-dev babelify uglifyify envify

Project Setup

# Create project structure
mkdir my-browserify-project
cd my-browserify-project

# Initialize package.json
npm init -y

# Install Browserify and dependencies
npm install --save-dev browserify babelify @babel/core @babel/preset-env

# Create source directories
mkdir -p src/{js,css}
mkdir dist

# Create entry point
touch src/js/main.js

Package.json Scripts

{
  "name": "my-browserify-project",
  "version": "1.0.0",
  "scripts": {
    "build": "browserify src/js/main.js -o dist/bundle.js",
    "build:watch": "watchify src/js/main.js -o dist/bundle.js -v",
    "build:prod": "browserify src/js/main.js -t [ babelify --presets [ @babel/preset-env ] ] -t uglifyify -o dist/bundle.min.js",
    "dev": "budo src/js/main.js:bundle.js --live --open",
    "test": "tape test/*.js | tap-spec"
  },
  "browserify": {
    "transform": [
      ["babelify", {
        "presets": ["@babel/preset-env"]
      }]
    ]
  }
}

Getting Started

Basic Module Structure

// src/js/math.js - A simple module
function add(a, b) {
  return a + b;
}

function multiply(a, b) {
  return a * b;
}

function subtract(a, b) {
  return a - b;
}

// Export functions
module.exports = {
  add: add,
  multiply: multiply,
  subtract: subtract
};

// Or using shorthand
module.exports = { add, multiply, subtract };
// src/js/utils.js - Utility functions
const capitalize = (str) => {
  return str.charAt(0).toUpperCase() + str.slice(1);
};

const formatDate = (date) => {
  return date.toLocaleDateString();
};

const debounce = (func, wait) => {
  let timeout;
  return function executedFunction(...args) {
    const later = () => {
      clearTimeout(timeout);
      func(...args);
    };
    clearTimeout(timeout);
    timeout = setTimeout(later, wait);
  };
};

module.exports = {
  capitalize,
  formatDate,
  debounce
};

Main Entry Point

// src/js/main.js - Application entry point
const math = require('./math');
const utils = require('./utils');
const $ = require('jquery'); // npm module

// Use local modules
console.log('2 + 3 =', math.add(2, 3));
console.log('4 * 5 =', math.multiply(4, 5));

// Use utility functions
const title = utils.capitalize('hello world');
console.log('Capitalized:', title);

// Use npm modules
$(document).ready(function() {
  $('body').append('<h1>' + title + '</h1>');
  
  // Add some interactivity
  $('h1').click(function() {
    $(this).css('color', 'blue');
  });
});

// Export for testing
if (typeof module !== 'undefined' && module.exports) {
  module.exports = { math, utils };
}

HTML Integration

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Browserify Demo</title>
</head>
<body>
    <div id="app">
        <h2>Browserify Application</h2>
        <button id="calculate">Calculate</button>
        <div id="result"></div>
    </div>
    
    <!-- Include the bundled JavaScript -->
    <script src="dist/bundle.js"></script>
</body>
</html>

Basic Usage

Simple Bundle Creation

# Basic bundling
browserify src/js/main.js -o dist/bundle.js

# Bundle with verbose output
browserify src/js/main.js -o dist/bundle.js -v

# Bundle to stdout
browserify src/js/main.js

# Bundle multiple entry points
browserify src/js/main.js src/js/admin.js -o dist/bundle.js

Using Transforms

# Bundle with Babel transform
browserify src/js/main.js -t babelify -o dist/bundle.js

# Bundle with multiple transforms
browserify src/js/main.js -t babelify -t uglifyify -o dist/bundle.js

# Transform with options
browserify src/js/main.js -t [ babelify --presets [ @babel/preset-env ] ] -o dist/bundle.js

Watch Mode

# Install watchify
npm install --save-dev watchify

# Watch for changes
watchify src/js/main.js -o dist/bundle.js -v

# Watch with transforms
watchify src/js/main.js -t babelify -o dist/bundle.js -v

# Watch with polling (for network drives)
watchify src/js/main.js -o dist/bundle.js -v --poll

Command Line Interface

Basic Commands

# Bundle a file
browserify input.js -o output.js

# Bundle to stdout
browserify input.js > output.js

# Bundle with debug info
browserify input.js -d -o output.js

# Bundle with standalone UMD
browserify input.js -s MyModule -o output.js

Advanced Options

# Exclude modules
browserify input.js -x jquery -o output.js

# External dependencies
browserify input.js --external jquery -o output.js

# Ignore modules
browserify input.js --ignore fs -o output.js

# Insert global variables
browserify input.js --insert-globals -o output.js

# Detect globals
browserify input.js --detect-globals -o output.js

Transform Options

# Apply transforms
browserify input.js -t babelify -o output.js

# Transform with configuration
browserify input.js -t [ babelify --presets [ @babel/preset-env ] ] -o output.js

# Global transforms (apply to node_modules)
browserify input.js -g uglifyify -o output.js

# List available transforms
npm search browserify-transform

Plugin Options

# Use plugins
browserify input.js -p [ factor-bundle -o bundle1.js -o bundle2.js ] -o common.js

# Plugin with options
browserify input.js -p [ browserify-shim ] -o output.js

# Multiple plugins
browserify input.js -p plugin1 -p plugin2 -o output.js

Programmatic API

Basic API Usage

// build.js - Build script using Browserify API
const browserify = require('browserify');
const fs = require('fs');

// Create browserify instance
const b = browserify({
  entries: ['src/js/main.js'],
  debug: true // Enable source maps
});

// Add transforms
b.transform('babelify', {
  presets: ['@babel/preset-env']
});

// Bundle and write to file
b.bundle()
  .pipe(fs.createWriteStream('dist/bundle.js'))
  .on('finish', () => {
    console.log('Bundle created successfully!');
  })
  .on('error', (err) => {
    console.error('Bundle error:', err);
  });

Advanced API Configuration

const browserify = require('browserify');
const fs = require('fs');
const path = require('path');

// Advanced configuration
const b = browserify({
  entries: ['src/js/main.js'],
  debug: process.env.NODE_ENV !== 'production',
  cache: {},
  packageCache: {},
  fullPaths: false,
  
  // Transform options
  transform: [
    ['babelify', {
      presets: ['@babel/preset-env'],
      sourceMaps: true
    }]
  ],
  
  // Plugin options
  plugin: [
    ['factor-bundle', {
      outputs: ['dist/page1.js', 'dist/page2.js']
    }]
  ]
});

// Add external dependencies
b.external(['jquery', 'lodash']);

// Add ignore patterns
b.ignore('fs');
b.ignore('path');

// Bundle with error handling
function bundle() {
  return b.bundle()
    .on('error', function(err) {
      console.error('Browserify error:', err.message);
      this.emit('end');
    })
    .pipe(fs.createWriteStream('dist/bundle.js'));
}

// Initial bundle
bundle();

// Watch for changes (if using watchify)
if (process.env.NODE_ENV === 'development') {
  const watchify = require('watchify');
  const w = watchify(b);
  
  w.on('update', () => {
    console.log('Rebuilding...');
    bundle();
  });
  
  w.on('log', (msg) => {
    console.log(msg);
  });
}

Stream Processing

const browserify = require('browserify');
const through2 = require('through2');
const uglify = require('uglify-js');

// Custom stream processing
function createBundle() {
  const b = browserify('src/js/main.js');
  
  return b.bundle()
    .pipe(through2(function(chunk, enc, callback) {
      // Custom processing
      let code = chunk.toString();
      
      // Minify in production
      if (process.env.NODE_ENV === 'production') {
        const result = uglify.minify(code);
        code = result.code;
      }
      
      this.push(code);
      callback();
    }))
    .pipe(fs.createWriteStream('dist/bundle.js'));
}

createBundle();

Transforms

Babel Transform

# Install babelify
npm install --save-dev babelify @babel/core @babel/preset-env
// .babelrc
{
  "presets": ["@babel/preset-env"],
  "plugins": [
    "@babel/plugin-transform-arrow-functions",
    "@babel/plugin-transform-classes"
  ]
}
# Use with browserify
browserify src/js/main.js -t babelify -o dist/bundle.js

CoffeeScript Transform

# Install coffeeify
npm install --save-dev coffeeify coffee-script
# src/js/app.coffee
class Calculator
  constructor: ->
    @result = 0
  
  add: (num) ->
    @result += num
    @
  
  multiply: (num) ->
    @result *= num
    @
  
  getResult: ->
    @result

module.exports = Calculator
# Bundle CoffeeScript
browserify src/js/app.coffee -t coffeeify -o dist/bundle.js

TypeScript Transform

# Install tsify
npm install --save-dev tsify typescript
// src/js/app.ts
interface Calculator {
  add(a: number, b: number): number;
  multiply(a: number, b: number): number;
}

class BasicCalculator implements Calculator {
  add(a: number, b: number): number {
    return a + b;
  }
  
  multiply(a: number, b: number): number {
    return a * b;
  }
}

export default BasicCalculator;
# Bundle TypeScript
browserify src/js/app.ts -p tsify -o dist/bundle.js

CSS Transforms

# Install css transforms
npm install --save-dev browserify-css stringify
// Using browserify-css
const css = require('./styles.css');
document.head.appendChild(css);
# Bundle with CSS
browserify src/js/main.js -t browserify-css -o dist/bundle.js

Environment Variables

# Install envify
npm install --save-dev envify
// src/js/config.js
const config = {
  apiUrl: process.env.API_URL || 'http://localhost:3000',
  debug: process.env.NODE_ENV === 'development',
  version: process.env.npm_package_version
};

module.exports = config;
# Bundle with environment variables
API_URL=https://api.example.com browserify src/js/main.js -t envify -o dist/bundle.js

Plugins

Factor Bundle Plugin

# Install factor-bundle
npm install --save-dev factor-bundle
// Multiple entry points with shared dependencies
const browserify = require('browserify');

const b = browserify({
  entries: ['src/js/page1.js', 'src/js/page2.js']
});

b.plugin('factor-bundle', {
  outputs: ['dist/page1.js', 'dist/page2.js']
});

b.bundle().pipe(fs.createWriteStream('dist/common.js'));

Bundle Collapser

# Install bundle-collapser
npm install --save-dev bundle-collapser
// Reduce bundle size by collapsing modules
const b = browserify('src/js/main.js');
b.plugin('bundle-collapser/plugin');
b.bundle().pipe(fs.createWriteStream('dist/bundle.js'));

Browserify Shim

# Install browserify-shim
npm install --save-dev browserify-shim
// package.json
{
  "browserify": {
    "transform": ["browserify-shim"]
  },
  "browserify-shim": {
    "jquery": "global:jQuery",
    "bootstrap": {
      "depends": ["jquery"],
      "exports": "bootstrap"
    }
  }
}

Disc Plugin (Bundle Analysis)

# Install disc
npm install --save-dev disc
// Analyze bundle size
const browserify = require('browserify');
const disc = require('disc');

const b = browserify('src/js/main.js');
b.plugin(disc, {
  output: 'bundle-analysis.html',
  open: true
});
b.bundle().pipe(process.stdout);

Source Maps

Enabling Source Maps

# Enable debug mode for source maps
browserify src/js/main.js -d -o dist/bundle.js

# Source maps with transforms
browserify src/js/main.js -t babelify -d -o dist/bundle.js

Programmatic Source Maps

const browserify = require('browserify');
const exorcist = require('exorcist');

// External source maps
browserify('src/js/main.js', { debug: true })
  .bundle()
  .pipe(exorcist('dist/bundle.js.map'))
  .pipe(fs.createWriteStream('dist/bundle.js'));

Source Map Options

const b = browserify({
  entries: ['src/js/main.js'],
  debug: true,
  
  // Source map options
  sourceMaps: true,
  sourceMapPrefix: '/src',
  sourceRoot: '/src'
});

Inline Source Maps

// Inline source maps for development
const b = browserify({
  entries: ['src/js/main.js'],
  debug: true
});

// Transform with source maps
b.transform('babelify', {
  sourceMaps: 'inline'
});

External Dependencies

Creating Vendor Bundle

# Create vendor bundle with common libraries
browserify -r jquery -r lodash -r moment -o dist/vendor.js

# Create app bundle excluding vendor libraries
browserify src/js/main.js -x jquery -x lodash -x moment -o dist/app.js

Programmatic External Dependencies

// vendor.js - Create vendor bundle
const browserify = require('browserify');

const vendor = browserify();
vendor.require('jquery');
vendor.require('lodash');
vendor.require('moment');

vendor.bundle().pipe(fs.createWriteStream('dist/vendor.js'));

// app.js - Create app bundle
const app = browserify('src/js/main.js');
app.external('jquery');
app.external('lodash');
app.external('moment');

app.bundle().pipe(fs.createWriteStream('dist/app.js'));

HTML Integration

<!DOCTYPE html>
<html>
<head>
    <title>Multi-bundle App</title>
</head>
<body>
    <!-- Load vendor bundle first -->
    <script src="dist/vendor.js"></script>
    <!-- Then load app bundle -->
    <script src="dist/app.js"></script>
</body>
</html>

Dynamic Externals

// Dynamic external configuration
const externals = ['jquery', 'lodash', 'react', 'react-dom'];

const b = browserify('src/js/main.js');

externals.forEach(lib => {
  b.external(lib);
});

b.bundle().pipe(fs.createWriteStream('dist/app.js'));

Multiple Bundles

Factor Bundle Setup

// build-multiple.js
const browserify = require('browserify');
const factor = require('factor-bundle');

const b = browserify({
  entries: [
    'src/js/pages/home.js',
    'src/js/pages/about.js',
    'src/js/pages/contact.js'
  ]
});

b.plugin(factor, {
  outputs: [
    'dist/home.js',
    'dist/about.js',
    'dist/contact.js'
  ]
});

// Common bundle
b.bundle().pipe(fs.createWriteStream('dist/common.js'));

Page-specific Bundles

// src/js/pages/home.js
const common = require('../common');
const analytics = require('../analytics');

// Home page specific code
const homeController = {
  init() {
    console.log('Home page initialized');
    analytics.track('page_view', 'home');
  },
  
  setupCarousel() {
    // Home page carousel logic
  }
};

homeController.init();
module.exports = homeController;
// src/js/pages/about.js
const common = require('../common');

// About page specific code
const aboutController = {
  init() {
    console.log('About page initialized');
  },
  
  setupTeamGrid() {
    // About page team grid logic
  }
};

aboutController.init();
module.exports = aboutController;

Build Script for Multiple Bundles

// build-all.js
const browserify = require('browserify');
const fs = require('fs');
const path = require('path');

const pages = ['home', 'about', 'contact', 'products'];

// Build individual page bundles
pages.forEach(page => {
  const b = browserify(`src/js/pages/${page}.js`);
  
  // Add common externals
  b.external('jquery');
  b.external('lodash');
  
  b.bundle()
    .pipe(fs.createWriteStream(`dist/${page}.js`))
    .on('finish', () => {
      console.log(`${page}.js bundle created`);
    });
});

// Build vendor bundle
const vendor = browserify();
vendor.require('jquery');
vendor.require('lodash');

vendor.bundle()
  .pipe(fs.createWriteStream('dist/vendor.js'))
  .on('finish', () => {
    console.log('vendor.js bundle created');
  });

Development Workflow

Development Server

# Install budo (development server)
npm install --save-dev budo
// package.json scripts
{
  "scripts": {
    "dev": "budo src/js/main.js:bundle.js --live --open --port 3000",
    "dev:https": "budo src/js/main.js:bundle.js --live --open --ssl",
    "dev:host": "budo src/js/main.js:bundle.js --live --host 0.0.0.0"
  }
}
```### ライブリロード設定
```javascript
// dev-server.js
const budo = require('budo');
const babelify = require('babelify');

budo('src/js/main.js:bundle.js', {
  live: true,
  open: true,
  port: 3000,
  stream: process.stdout,
  
  // Browserify options
  browserify: {
    transform: [
      babelify.configure({
        presets: ['@babel/preset-env']
      })
    ],
    debug: true
  }
}).on('connect', (ev) => {
  console.log('Server running on %s', ev.uri);
});
```### ホットモジュール置換
```bash
# Install browserify-hmr
npm install --save-dev browserify-hmr
// src/js/main.js with HMR
const app = require('./app');

// Initialize app
app.init();

// Hot module replacement
if (module.hot) {
  module.hot.accept('./app', () => {
    const newApp = require('./app');
    newApp.init();
  });
}
```### 開発ビルドスクリプト
```javascript
// dev-build.js
const browserify = require('browserify');
const watchify = require('watchify');
const babelify = require('babelify');

// Create watchify instance
const b = watchify(browserify({
  entries: ['src/js/main.js'],
  cache: {},
  packageCache: {},
  debug: true
}));

// Add transforms
b.transform(babelify, {
  presets: ['@babel/preset-env']
});

// Bundle function
function bundle() {
  return b.bundle()
    .on('error', (err) => {
      console.error('Bundle error:', err.message);
    })
    .pipe(fs.createWriteStream('dist/bundle.js'))
    .on('finish', () => {
      console.log('Bundle updated');
    });
}

// Watch for changes
b.on('update', bundle);
b.on('log', console.log);

// Initial bundle
bundle();
```## 本番ビルド
```bash
# Install uglifyify
npm install --save-dev uglifyify
# Production build with minification
NODE_ENV=production browserify src/js/main.js -t babelify -g uglifyify -o dist/bundle.min.js
```### 圧縮
```javascript
// build-prod.js
const browserify = require('browserify');
const uglifyify = require('uglifyify');
const envify = require('envify');

// Set production environment
process.env.NODE_ENV = 'production';

const b = browserify({
  entries: ['src/js/main.js'],
  debug: false // Disable source maps for production
});

// Add transforms
b.transform('babelify', {
  presets: ['@babel/preset-env']
});

b.transform('envify', {
  NODE_ENV: 'production'
});

// Global transforms (apply to node_modules)
b.transform('uglifyify', {
  global: true,
  compress: {
    drop_console: true,
    drop_debugger: true
  }
});

// Bundle
b.bundle()
  .pipe(fs.createWriteStream('dist/bundle.min.js'))
  .on('finish', () => {
    console.log('Production bundle created');
  });
```### 本番ビルドスクリプト
```javascript
// analyze-bundle.js
const browserify = require('browserify');
const disc = require('disc');

const b = browserify('src/js/main.js');

b.plugin(disc, {
  output: 'bundle-analysis.html',
  open: true
});

b.bundle((err, buf) => {
  if (err) {
    console.error('Bundle error:', err);
  } else {
    console.log('Bundle size:', (buf.length / 1024).toFixed(2) + 'KB');
  }
});
```### バンドル分析
```javascript
// gzip-analysis.js
const browserify = require('browserify');
const zlib = require('zlib');

browserify('src/js/main.js')
  .bundle((err, buf) => {
    if (err) throw err;
    
    const size = buf.length;
    
    zlib.gzip(buf, (err, gzipped) => {
      if (err) throw err;
      
      const gzipSize = gzipped.length;
      
      console.log('Bundle size:', (size / 1024).toFixed(2) + 'KB');
      console.log('Gzipped size:', (gzipSize / 1024).toFixed(2) + 'KB');
      console.log('Compression ratio:', ((1 - gzipSize / size) * 100).toFixed(1) + '%');
    });
  });
```### Gzip分析
```bash
# Install tape
npm install --save-dev tape tap-spec
// test/math.test.js
const test = require('tape');
const math = require('../src/js/math');

test('Math module tests', (t) => {
  t.equal(math.add(2, 3), 5, 'Addition works correctly');
  t.equal(math.multiply(4, 5), 20, 'Multiplication works correctly');
  t.equal(math.subtract(10, 3), 7, 'Subtraction works correctly');
  t.end();
});
// package.json
{
  "scripts": {
    "test": "tape test/*.js | tap-spec"
  }
}
```## テスト
```bash
# Install testling
npm install --save-dev testling
// package.json
{
  "testling": {
    "files": "test/*.js",
    "browsers": [
      "ie/9..latest",
      "chrome/latest",
      "firefox/latest",
      "safari/latest"
    ]
  }
}
```### Tapeによる単体テスト
```bash
# Install karma and browserify
npm install --save-dev karma karma-browserify karma-chrome-launcher karma-jasmine
// karma.conf.js
module.exports = function(config) {
  config.set({
    frameworks: ['jasmine', 'browserify'],
    
    files: [
      'test/**/*.js'
    ],
    
    preprocessors: {
      'test/**/*.js': ['browserify']
    },
    
    browserify: {
      debug: true,
      transform: ['babelify']
    },
    
    browsers: ['Chrome'],
    
    singleRun: true
  });
};
```### ブラウザテスト
```javascript
// test/api.test.js
const test = require('tape');
const proxyquire = require('proxyquire');

// Mock HTTP requests
const apiModule = proxyquire('../src/js/api', {
  'http': {
    get: (url, callback) => {
      // Mock response
      callback({
        statusCode: 200,
        body: JSON.stringify({ success: true })
      });
    }
  }
});

test('API module tests', (t) => {
  apiModule.fetchData((err, data) => {
    t.error(err, 'No error occurred');
    t.ok(data.success, 'API returned success');
    t.end();
  });
});
```### Karmaの統合
```javascript
// transforms/custom-transform.js
const through = require('through2');
const path = require('path');

module.exports = function(file, opts) {
  // Only process .custom files
  if (path.extname(file) !== '.custom') {
    return through();
  }
  
  let content = '';
  
  return through(
    function(chunk, enc, callback) {
      content += chunk.toString();
      callback();
    },
    function(callback) {
      // Transform the content
      const transformed = content
        .replace(/CUSTOM_SYNTAX/g, 'JavaScript equivalent')
        .replace(/\$\{([^}]+)\}/g, '" + $1 + "');
      
      this.push('module.exports = ' + JSON.stringify(transformed));
      callback();
    }
  );
};
```### モッキングとスタビング
```javascript
// plugins/custom-plugin.js
module.exports = function(b, opts) {
  opts = opts || {};
  
  b.on('bundle', function(bundle) {
    console.log('Bundle started');
  });
  
  b.pipeline.get('record').push(through.obj(function(row, enc, next) {
    // Modify module records
    if (row.file.endsWith('.special.js')) {
      row.source = '// Special processing\n' + row.source;
    }
    this.push(row);
    next();
  }));
};
```## 高度な機能
```javascript
// conditional-build.js
const browserify = require('browserify');

const isProduction = process.env.NODE_ENV === 'production';
const isDevelopment = !isProduction;

const b = browserify({
  entries: ['src/js/main.js'],
  debug: isDevelopment
});

// Conditional transforms
if (isDevelopment) {
  b.transform('browserify-hmr');
} else {
  b.transform('uglifyify', { global: true });
}

// Conditional plugins
if (isProduction) {
  b.plugin('bundle-collapser/plugin');
}

b.bundle().pipe(fs.createWriteStream(
  isProduction ? 'dist/bundle.min.js' : 'dist/bundle.js'
));
```### カスタムトランスフォーム
```javascript
// src/js/dynamic-loader.js
const loadModule = (moduleName) => {
  return new Promise((resolve, reject) => {
    // Dynamic require (note: this needs special handling in browserify)
    try {
      const module = require(`./modules/${moduleName}`);
      resolve(module);
    } catch (err) {
      reject(err);
    }
  });
};

// Usage
loadModule('feature-a').then(module => {
  module.init();
});
```### プラグイン開発
```javascript
// Split bundles by feature
const features = ['auth', 'dashboard', 'settings'];

features.forEach(feature => {
  const b = browserify(`src/js/features/${feature}/index.js`);
  
  // External common dependencies
  b.external('jquery');
  b.external('lodash');
  
  b.bundle()
    .pipe(fs.createWriteStream(`dist/${feature}.js`));
});
```### 条件付きバンドリング
```javascript
// src/js/lazy-loader.js
const lazyLoad = (modulePath) => {
  return new Promise((resolve) => {
    // Simulate dynamic loading
    setTimeout(() => {
      const module = require(modulePath);
      resolve(module);
    }, 100);
  });
};

// Usage in main app
document.getElementById('load-feature').addEventListener('click', () => {
  lazyLoad('./features/advanced-feature').then(feature => {
    feature.initialize();
  });
});
```### 動的インポート
```javascript
// advanced-splitting.js
const browserify = require('browserify');
const factor = require('factor-bundle');

// Define entry points
const entries = [
  'src/js/pages/home.js',
  'src/js/pages/products.js',
  'src/js/pages/checkout.js'
];

const b = browserify({
  entries: entries,
  debug: false
});

// Configure factor bundle
b.plugin(factor, {
  outputs: [
    'dist/home.js',
    'dist/products.js',
    'dist/checkout.js'
  ],
  threshold: 1 // Minimum number of bundles a module must be in to be factored out
});

// Common bundle
b.bundle()
  .pipe(fs.createWriteStream('dist/common.js'))
  .on('finish', () => {
    console.log('Code splitting completed');
  });
```## パフォーマンス最適化
```javascript
// optimize-bundle.js
const browserify = require('browserify');
const uglifyify = require('uglifyify');
const bundleCollapser = require('bundle-collapser/plugin');

const b = browserify('src/js/main.js');

// Optimization transforms and plugins
b.transform('uglifyify', {
  global: true,
  compress: {
    drop_console: true,
    drop_debugger: true,
    pure_funcs: ['console.log', 'console.info']
  },
  mangle: {
    reserved: ['$', 'jQuery']
  }
});

b.plugin(bundleCollapser);

// Ignore unnecessary modules
b.ignore('fs');
b.ignore('path');
b.ignore('crypto');

b.bundle()
  .pipe(fs.createWriteStream('dist/bundle.optimized.js'));
```### バンドル分割
```bash
# Enable debug mode for detailed output
browserify src/js/main.js -d -o dist/bundle.js

# Verbose output
browserify src/js/main.js -v -o dist/bundle.js

ソースマップデバッグ

// Enable source maps in development
const b = browserify({
  entries: ['src/js/main.js'],
  debug: true, // Enables inline source maps
  fullPaths: true // Keep full paths for better debugging
});

バンドル分析

// debug-bundle.js
const browserify = require('browserify');
const deps = require('browserify-deps');

// Analyze dependencies
browserify('src/js/main.js')
  .pipeline.get('deps')
  .pipe(deps())
  .pipe(through.obj(function(row, enc, next) {
    console.log('Module:', row.file);
    console.log('Dependencies:', row.deps);
    console.log('---');
    next();
  }));

エラーハンドリング

// error-handling.js
const browserify = require('browserify');

const b = browserify('src/js/main.js');

b.bundle()
  .on('error', function(err) {
    console.error('Browserify error:');
    console.error('Message:', err.message);
    console.error('File:', err.filename);
    console.error('Line:', err.line);
    console.error('Column:', err.column);
    
    // Don't exit process in watch mode
    this.emit('end');
  })
  .pipe(fs.createWriteStream('dist/bundle.js'));

プロファイリング

// profile-build.js
const browserify = require('browserify');

console.time('Bundle time');

browserify('src/js/main.js')
  .bundle()
  .pipe(fs.createWriteStream('dist/bundle.js'))
  .on('finish', () => {
    console.timeEnd('Bundle time');
    
    // Memory usage
    const used = process.memoryUsage();
    console.log('Memory usage:');
    for (let key in used) {
      console.log(`${key}: ${Math.round(used[key] / 1024 / 1024 * 100) / 100} MB`);
    }
  });

マイグレーション

Webpackから

// webpack.config.js equivalent in Browserify
// Webpack:
// module.exports = {
//   entry: './src/index.js',
//   output: {
//     filename: 'bundle.js',
//     path: path.resolve(__dirname, 'dist')
//   },
//   module: {
//     rules: [{
//       test: /\.js$/,
//       use: 'babel-loader'
//     }]
//   }
// };

// Browserify equivalent:
const browserify = require('browserify');

browserify('./src/index.js')
  .transform('babelify')
  .bundle()
  .pipe(fs.createWriteStream('dist/bundle.js'));

RequireJSから

// RequireJS config equivalent
// requirejs.config({
//   baseUrl: 'src/js',
//   paths: {
//     'jquery': 'vendor/jquery',
//     'lodash': 'vendor/lodash'
//   }
// });

// Browserify approach - use npm modules
// npm install jquery lodash

// src/js/main.js
const $ = require('jquery');
const _ = require('lodash');

// Use modules normally
$('#app').text('Hello from Browserify');

マイグレーションチェックリスト

  • AMD/RequireJSモジュールをCommonJSに変換
  • ベンダーライブラリのnpm同等品をインストール
  • Browserifyを使用するようにビルドスクリプトを更新
  • 前処理用のトランスフォームを設定
  • watchifyで開発ワークフローをセットアップ
  • バンドルされたスクリプトを使用するようにHTMLを更新
  • マイグレーション後にすべての機能をテスト

ベストプラクティス

モジュール構成

// Good: Clear module structure
// src/js/modules/user.js
const api = require('../api');
const utils = require('../utils');

class User {
  constructor(data) {
    this.data = data;
  }
  
  save() {
    return api.post('/users', this.data);
  }
  
  format() {
    return utils.formatUser(this.data);
  }
}

module.exports = User;

依存関係管理

// package.json - Clear separation of dependencies
{
  "dependencies": {
    "jquery": "^3.6.0",
    "lodash": "^4.17.21"
  },
  "devDependencies": {
    "browserify": "^17.0.0",
    "babelify": "^10.0.0",
    "watchify": "^4.0.0"
  }
}

ビルド設定

// build-config.js - Centralized configuration
const config = {
  entry: 'src/js/main.js',
  output: 'dist/bundle.js',
  
  transforms: [
    ['babelify', { presets: ['@babel/preset-env'] }]
  ],
  
  plugins: process.env.NODE_ENV === 'production' ? [
    'bundle-collapser/plugin'
  ] : [],
  
  external: ['jquery', 'lodash'],
  
  debug: process.env.NODE_ENV !== 'production'
};

module.exports = config;

パフォーマンスのベストプラクティス

  • 大きなライブラリは外部バンドルを使用
  • 大規模アプリケーションではコード分割を実装
  • ソースマップは開発時のみ有効にする
  • トランスフォームは慎重に使用 - ビルド時間が増加
  • ボトルネックを特定するためにビルドをプロファイリング

開発のベストプラクティス

  • 開発中の高速リビルドに watchify を使用
  • budioなどのツールでライブリロードをセットアップ
  • ビルドスクリプトで適切なエラーハンドリングを実装
  • より良いデバッグ体験のためにデバッグモードを使用
  • 一貫性のためにトランスフォームをpackage.jsonに保持

本番環境のベストプラクティス

  • uglifyifyでバンドルを圧縮
  • envifyでデバッグコードを削除
  • バンドルサイズを定期的に分析
  • サーバーでgzip圧縮を使用
  • 適切なキャッシングヘッダーを実装

概要

Browserifyは、Node.jsスタイルのモジュールシステムをブラウザにもたらす強力なツールです。主な機能は以下の通りです:

  • CommonJSモジュール: ブラウザでrequire()とmodule.exportsを使用
  • NPM統合: npmエコシステム全体を活用
  • トランスフォームシステム: Babel、TypeScript、CoffeeScriptなどでファイルを前処理
  • プラグインアーキテクチャ: プラグインで機能を拡張
  • ソースマップ: ブラウザで元のソースコードをデバッグ
  • コード分割: パフォーマンス向上のための複数バンドル作成
  • 開発ツール: ウォッチモード、ライブリロード、デバッグサポート
  • 本番環境対応: 圧縮、最適化、バンドル分析

Browserifyを使用することで、Node.jsと同じモジュールパターンでフロントエンドコードを整理でき、コードベースの保守性が向上し、フロントエンドとバックエンド間でコードを共有できます。