Guia Rápido do Browserify
Browserify - Browser-side require()
O Browserify permite usar require('modules') no navegador agrupando todas as suas dependências. Ele usa o mesmo sistema de módulos do Node.js, permitindo usar módulos npm no navegador e organizar seu código com módulos CommonJS.
(This section appears to be empty in the original text, so no translation is needed)Sumário de Conteúdos
- Instalação
- Primeiros Passos
- Uso Básico
- Interface de Linha de Comando
- API Programática
- Transformações
- Plugins
- Mapas de Origem
- Dependências Externas
- Múltiplos Pacotes
- Fluxo de Trabalho de Desenvolvimento
- Builds de Produção
- Testes
- Recursos Avançados
- Otimização de Desempenho
- Depuração
- Migração
- Melhores Práticas
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"
}
}
```### Configuração de Recarga Ao Vivo
```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);
});
```### Substituição de Módulo Quente
```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();
});
}
```### Script de Build de Desenvolvimento
```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();
```## Builds de Produção
```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
```### Minificação
```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');
});
```### Script de Build de Produção
```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');
}
});
```### Análise de Bundle
```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) + '%');
});
});
```### Análise 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"
}
}
```## Testes
```bash
# Install testling
npm install --save-dev testling
// package.json
{
"testling": {
"files": "test/*.js",
"browsers": [
"ie/9..latest",
"chrome/latest",
"firefox/latest",
"safari/latest"
]
}
}
```### Testes Unitários com 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
});
};
```### Testes em Navegador
```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();
});
});
```### Integração 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();
}
);
};
```### Mocking e Stubbing
```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();
}));
};
```## Recursos Avançados
```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'
));
```### Transformações Personalizadas
```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();
});
```### Desenvolvimento de Plugin
```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`));
});
```### Bundling Condicional
```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();
});
});
```### Importações Dinâmicas
```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');
});
```## Otimização de Desempenho
```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'));
```### Divisão de Bundle
```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
```### Depuração de Source Map
```javascript
// 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
});
```### Análise de Bundle
```javascript
// 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();
}));
```### Tratamento de Erros
```javascript
// 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'));
```### Profiling
```javascript
// 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`);
}
});
```## Migração
### De Webpack
```javascript
// 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'));
```### De RequireJS
```javascript
// 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');
```### Lista de Verificação de Migração
- [ ] Converter módulos AMD/RequireJS para CommonJS
- [ ] Instalar equivalentes npm de bibliotecas de terceiros
- [ ] Atualizar scripts de build para usar Browserify
- [ ] Configurar transformações para pré-processamento
- [ ] Configurar fluxo de desenvolvimento com watchify
- [ ] Atualizar HTML para usar scripts empacotados
- [ ] Testar toda funcionalidade após migração
## Melhores Práticas
### Organização de Módulos
```javascript
// 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;
```### Gerenciamento de Dependências
```json
// 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"
}
}
```### Configuração de Build
```javascript
// 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;
```### Melhores Práticas de Performance
- **Usar bundles externos** para bibliotecas grandes
- **Implementar code splitting** para aplicações grandes
- **Habilitar source maps** apenas em desenvolvimento
- **Usar transformações com cautela** - elas aumentam o tempo de build
- **Fazer profile dos builds** para identificar gargalos
### Melhores Práticas de Desenvolvimento
- **Usar watchify** para rebuilds rápidos durante desenvolvimento
- **Configurar live reload** com budo ou ferramentas similares
- **Implementar tratamento de erros adequado** em scripts de build
- **Usar modo de depuração** para melhor experiência de debugging
- **Manter transformações no package.json** para consistência
### Melhores Práticas de Produção
- **Minificar bundles** com uglifyify
- **Remover código de depuração** com envify
- **Analisar tamanho do bundle** regularmente
- **Usar compressão gzip** no servidor
- **Implementar headers de cache adequados**
---
## Resumo
Browserify é uma ferramenta poderosa que traz o sistema de módulos do Node.js para o navegador. Principais recursos incluem:
- **Módulos CommonJS**: Use require() e module.exports no navegador
- **Integração com NPM**: Aproveite todo o ecossistema npm
- **Sistema de Transformação**: Pré-processar arquivos com Babel, TypeScript, CoffeeScript, etc.
- **Arquitetura de Plugins**: Estender funcionalidade com plugins
- **Source Maps**: Depurar código-fonte original no navegador
- **Code Splitting**: Criar múltiplos bundles para melhor performance
- **Ferramentas de Desenvolvimento**: Modo de observação, live reload e suporte a debugging
- **Pronto para Produção**: Minificação, otimização e análise de bundle
Usando Browserify, você pode organizar seu código frontend com os mesmos padrões de módulos usados no Node.js, tornando sua base de código mais manutenível e permitindo compartilhar código entre frontend e backend.
<script>
function copyToClipboard() {
const commands = document.querySelectorAll('code');
let allCommands = '';
commands.forEach(cmd => allCommands += cmd.textContent + '\n');
navigator.clipboard.writeText(allCommands);
alert('Todos os comandos copiados para a área de transferência!');
}
function generatePDF() {
window.print();
}
</script>