Full Code of petehunt/webpack-howto for AI

master dcd772bc5ff5 cached
13 files
35.3 KB
10.2k tokens
1 requests
Download .txt
Repository: petehunt/webpack-howto
Branch: master
Commit: dcd772bc5ff5
Files: 13
Total size: 35.3 KB

Directory structure:
gitextract_luql2mqu/

├── README-es.md
├── README-tr.md
├── README-zh.md
├── README.md
└── example/
    ├── .gitignore
    ├── index.html
    ├── modules/
    │   ├── About.js
    │   ├── App.css
    │   ├── App.js
    │   ├── Home.js
    │   └── main.js
    ├── package.json
    └── webpack.config.js

================================================
FILE CONTENTS
================================================

================================================
FILE: README-es.md
================================================
# webpack-howto

## Objetivo de esta guía

Esta es una guía sobre como lograr lo que uno quiere usando webpack. Incluye la mayoría de las cosas que utilizamos en Instagram y nada que no utilicemos.

Mi consejo: empezar con esta guía como tu documentación sobre webpack, y luego mirar la documentación oficial para aclarar conceptos y/o detalles.

## Pre-Requisitos

  * Saber sobre browserify, RequireJS o similares
  * Ver valor en:
    * Partir/fraccionar paquetes (Bundle splitting)
    * Carga asincrónica (Async loading)
    * Empaquetar contenido estático como imágenes y CSS

## 1. Por que webpack?


  * **Es como browserify** pero puede fraccionar nuestra app en múltiples archivos. Si tenemos múltiples paginas en una SPA (Single Page App), el usuario solo descarga el contenido correspondiente a la pagina actual. Si luego visita otra pagina, no vuelve a descargar código en común o repetido.

  * **Generalmente reemplaza a grunt o gulp** porque puede construir y empaquetar CSS, CSS pre-procesado, lenguajes compilables-a-JS e imágenes, entre otras cosas.

Soporta AMA, CommonJS y otros sistemas de módulos (Angular, ES6). Si no sabes que usar, usa CommonJS.

## 2. Webpack para gente que usa Browserify

Estos son equivalentes:

```js
browserify main.js > bundle.js
```

```js
webpack main.js bundle.js
```

Sin embargo, webpack es mas poderoso que Browserify, por lo que generalmente queremos crear el archivo `webpack.config.js` para organizarnos mejor:

```js
// webpack.config.js
module.exports = {
  entry: './main.js',
  output: {
    filename: 'bundle.js'
  }
};
```

Esto es puramente JS, por lo que podemos escribir Código Real adentro.

## 3. Como llamar a webpack

Entrar al directorio que contiene `webpack.config.js` y ejecutar:

  * `webpack` para construir una vez para desarrollo
  * `webpack -p` para construir una vez para producción (minificado)
  * `webpack --watch` para construir de forma continua e incremental en desarrollo (rápido!)
  * `webpack -d` para incluir mapas fuente (source maps)

## 4. Lenguajes Compilables-a-JS

El equivalente en webpack para las transformaciones de browserify y los plugins de RequireJS, es un **cargador (loader)**. Aquí vemos como podemos hacer que webpack cargue soporte para CoffeeScript y JSX+ES6 (debes ejecutar `npm install babel-loader coffee-loader` primero):

Ver también las [instrucciones de instalación babel-loader](https://www.npmjs.com/package/babel-loader) para dependencias adicionales (tl;dr ejecutar `npm install babel-core babel-preset-es2015 babel-preset-react`).

```js
// webpack.config.js
module.exports = {
  entry: './main.js',
  output: {
    filename: 'bundle.js'
  },
  module: {
    loaders: [
      { test: /\.coffee$/, loader: 'coffee-loader' },
      {
        test: /\.js$/,
        loader: 'babel-loader',
        query: {
          presets: ['es2015', 'react']
        }
      }
    ]
  }
};
```

Para habilitar requerir archivos sin especificar la extensión, hay que agregar el parámetro `resolve.extensions` declarando que tipos de archivos va a buscar webpack:

```js
// webpack.config.js
module.exports = {
  entry: './main.js',
  output: {
    filename: 'bundle.js'
  },
  module: {
    loaders: [
      { test: /\.coffee$/, loader: 'coffee-loader' },
      {
        test: /\.js$/,
        loader: 'babel-loader',
        query: {
          presets: ['es2015', 'react']
        }
      }
    ]
  },
  resolve: {
    // ahora podemos hacer require('file') en vez de require('file.coffee')
    extensions: ['', '.js', '.json', '.coffee']
  }
};
```


## 5. Estilos (CSS) e imágenes

Primero actualizamos el código para incluir contenido estático usando `require()`

```js
require('./bootstrap.css');
require('./myapp.less');

var img = document.createElement('img');
img.src = require('./glyph.png');
```

Cuando requerimos CSS (o less, etc), webpack incluye el CSS en forma de string en una linea dentro del paquete de JS, y `require()` va luego a insertar los tags de estilo `<style>` en la pagina. Cuando requerimos imágenes, webpack incluye una linea en el paquete con la URL de la imagen, y luego la retorna desde el `require()`.

Una vez mas, debemos indicarle a webpack como realizar esto (nuevamente utilizando cargadores)

```js
// webpack.config.js
module.exports = {
  entry: './main.js',
  output: {
    path: './build', // Aquí van las imágenes y JS
    publicPath: 'http://mycdn.com/', // Esta ruta se utiliza para generar las URLs a por ejemplo, las imágenes
    filename: 'bundle.js'
  },
  module: {
    loaders: [
      { test: /\.less$/, loader: 'style-loader!css-loader!less-loader' }, // usar ! para encadenar cargadores
      { test: /\.css$/, loader: 'style-loader!css-loader' },
      { test: /\.(png|jpg)$/, loader: 'url-loader?limit=8192' } // URLs base64 en linea para imágenes <=8k, URLs directas para el resto
    ]
  }
};
```

## 6. Banderas para funciones

Cuando tenemos código que queremos despachar unicamente a nuestro ambiente de desarrollo (como extra logging) o ambientes de preproducción (como funciones en alpha para testear internamente), debemos usar globales mágicas:

```js
if (__DEV__) {
  console.warn('Extra logging');
}
// ...
if (__PRERELEASE__) {
  mostrarFuncionOculta();
}
```

Y luego informar esas globales mágicas a webpack:

```js
// webpack.config.js

// definePlugin recibe strings crudas y la inyecta, por lo que es posible incluir JS si se desea.
var definePlugin = new webpack.DefinePlugin({
  __DEV__: JSON.stringify(JSON.parse(process.env.BUILD_DEV || 'true')),
  __PRERELEASE__: JSON.stringify(JSON.parse(process.env.BUILD_PRERELEASE || 'false'))
});

module.exports = {
  entry: './main.js',
  output: {
    filename: 'bundle.js'
  },
  plugins: [definePlugin]
};
```

Ahora podemos construir usando `BUILD_DEV=1 BUILD_PRERELEASE=1 webpack` desde la consola. Nótese que ya que `webpack -p` ejecuta la función de uglify para eliminar código muerto, cualquier cosa incluida dentro de ese tipo de bloques va a ser eliminado y por ende, no corremos el riesgo de difundir rutas o cogido secreto.

## 7. Múltiples puntos de entrada

Digamos que tenemos una pagina de perfil y una pagina de feed. No queremos que el usuario tenga que descargar el contenido del feed si solo va a visitar el perfil. Entonces creamos múltiples paquetes: creamos un "modulo principal" (llamado punto de entrada) para cada pagina:

```js
// webpack.config.js
module.exports = {
  entry: {
    Profile: './profile.js',
    Feed: './feed.js'
  },
  output: {
    path: 'build',
    filename: '[name].js' // La plantilla utiliza los nombres de la entradas definidas arriba
  }
};
```

Para el perfil, insertamos `<script src="build/Profile.js"></script>` en nuestra pagina; y luego lo mismo para el feed.

## 8. Optimizando código en común

El Feed y el Perfil probablemente comparten bastante código (como React u hojas de estilos y componentes en común). webpack es inteligente: puede darse cuenta que cosas tienen en común y crear un paquete compartido que puede ser cacheado entre paginas:

```js
// webpack.config.js

var webpack = require('webpack');

var commonsPlugin =
  new webpack.optimize.CommonsChunkPlugin('common.js');

module.exports = {
  entry: {
    Profile: './profile.js',
    Feed: './feed.js'
  },
  output: {
    path: 'build',
    filename: '[name].js' // La plantilla utiliza los nombres de la entradas definidas arriba
  },
  plugins: [commonsPlugin]
};
```

Agregando `<script src="build/common.js"></script>` por encima del tag de script que agregamos en el paso previo, ya podes disfrutar de cachear el código compartido.

## 9. Carga asincrónica

CommonJS es síncrono pero webpack nos provee una forma de especificar dependencias de manera asincrónica. Esto es util para routers desde el lado del cliente, donde queremos el router presente en todas las paginas, pero no queremos descargar funciones y/o contenido hasta que no sean realmente necesarias.

Especificamos el **punto de quiebre** donde queremos cargar de forma asincrónica. Por ejemplo:

```js
if (window.location.pathname === '/feed') {
  showLoadingState();
  require.ensure([], function() { // esta sintaxis es extraña pero funciona
    hideLoadingState();
    require('./feed').show(); // cuando se llama a esta función, webpack garantiza que el modulo sea accesible de forma sincrónica.
  });
} else if (window.location.pathname === '/profile') {
  showLoadingState();
  require.ensure([], function() {
    hideLoadingState();
    require('./profile').show();
  });
}
```

webpack va a realizar el trabajo duro y generar **pedazos (chunks)** y cargarlos por nosotros.

webpack asume que esos archivos están en el directorio madre cuando los cargamos. Podemos usar `output.publicPath` para configurar eso:

```js
// webpack.config.js
output: {
    path: "/home/proj/public/assets", // ruta donde webpack va a construir tus archivos
    publicPath: "/assets/" // ruta que va a ser utilizada a la hora de requerir archivos
}
```

## Recursos adicionales

Para echar un vistazo a un ejemplo del mundo real sobre como un equipo exitoso esta utilizando webpack: http://youtu.be/VkTCL6Nqm6Y
Es Pete Hunt (autor de esta guía) en la OSCon hablando sobre webpack en Instagram.com

## FAQ

### webpack no parece modular

webpack es **extremadamente** modular. Lo que hace grandioso a webpack es que permite que los plugins se inyecten a si mismos en mas puntos durante el proceso de construcción, cuando lo comparamos con las alternativas como browserify y RequireJS. Muchas cosas que parecen parte del núcleo son en realidad simplemente plugins que son cargados por default, y pueden ser anulaos o sobrescritos (por ejemplo, el parseador para require() de CommonJS).


================================================
FILE: README-tr.md
================================================
# webpack-howto

## Bu kılavuzun amacı

Bu kıtapçık, webpack ile işlerin nasıl yürüdüğünü gösterir. Instagram'da kullandığımız ve hiç kullanmadığımız birçok şeyi içerir.

Size tavsiyem: başlangıç için bu kılavuzu webpack dökümanı olarak kullanın daha sonra bazı şeyleri netleştirmek için webpack'in resmi dökümanlarına bakın.

## Ön koşullar

  * Browserify, RequireJS veya benzerlerini bilmelisiniz
  * Önemini bilmelisiniz:
    * Kodu parçalara ayırmak (Bundle splitting)
    * Asenkron yükleme (Async loading)
    * Resimler ve CSS dosyaları gibi statik dosyaları paketleme

## 1. Neden webpack?


  * **Browserify'a benziyor** ama uygulamanızı birden çok dosya şeklinde parçalara ayırıyor, bölüyor. Tek sayfalık (single-page) bir uygulamada birden fazla sayfanız varsa, kullanıcı yalnızca bu sayfa için gerekli kodları indirir. Eğer kullanıcı başka bir sayfaya giderse ortak kodu tekrar indirmesine gerek kalmaz.

  * **Genellikle grunt ve gulp yerine geçer** çünkü CSS, işlenmemiş CSS, compile-to-JS dilleri ve resimleri diğer şeylerin arasından bundle ve build edebilir.

Diğer modül sistemleri arasından (Angular, ES6) AMD ve CommonJS'i destekler. Eğer ne kullanacağınızı bilmiyorsanız CommonJS kullanın.

## 2. Browserify kullananlar için Webpack

Bunlar eşdeğerdir:

```js
browserify main.js > bundle.js
```

```js
webpack main.js bundle.js
```

Fakat webpack, Browserify'dan daha güçlüdür. Bu yüzden genellikle işleri organize hale getirmek için `webpack.config.js` oluşturmak isteyebilirsiniz.

```js
// webpack.config.js
module.exports = {
  entry: './main.js',
  output: {
    filename: 'bundle.js'       
  }
};
```

Normal bir JS dosyası olduğu için içerisine kod yazmakta özgürsünüz.

## 3. Webpack nasıl başlatılır

`webpack.config.js` dosyasının bulunduğu dizine geçin ve aşağıdaki komutları çalıştırın:

  * `webpack` geliştirme süreci için tek seferlik build işlemi
  * `webpack -p` üretim süreci için tek seferlik build işlemi (minification)
  * `webpack --watch` geliştirme sürecinde sürekli devam eden build işlemleri için
  * `webpack -d` kaynak haritalarını (source maps) dahil etmek için

## 4. Compile-to-JS dilleri

**loader** browserify dönüşümlerinin ve RequireJS eklentilerinin webpack'teki karşılığıdır. webpack'e CoffeeScript ve Facebook JSX+ES6 desteğini şu şekilde öğretebilirsiniz (`npm install babel-loader coffee-loader` yapmalısınız):

Ek bağımlılıklar için [babel-loader kurulum talimatlarına](https://www.npmjs.com/package/babel-loader) bakınız (tl;dr run `npm install babel-core babel-preset-es2015 babel-preset-react`).

```js
// webpack.config.js
module.exports = {
  entry: './main.js',
  output: {
    filename: 'bundle.js'       
  },
  module: {
    loaders: [
      { test: /\.coffee$/, loader: 'coffee-loader' },
      {
        test: /\.js$/,
        loader: 'babel-loader',
        query: {
          presets: ['es2015', 'react']
        }
      }
    ]
  }
};
```

Dosya uzantısı belirtmeden require işlemi yapabilmek için `resolve.extensions` parametresini webpack'in hangi dosyalara bakacağını da belirterek eklemelisiniz.

```js
// webpack.config.js
module.exports = {
  entry: './main.js',
  output: {
    filename: 'bundle.js'       
  },
  module: {
    loaders: [
      { test: /\.coffee$/, loader: 'coffee-loader' },
      {
        test: /\.js$/,
        loader: 'babel-loader',
        query: {
          presets: ['es2015', 'react']
        }
      }
    ]
  },
  resolve: {
    //artık require('file.coffee') yerine require('file') kullanabilirsiniz
    extensions: ['', '.js', '.json', '.coffee'] 
  }
};
```


## 5. Stylesheets ve resimler

İlk önce kodunuzu statik dosyaları `require()` ile kullanabilmek için update edin:

```js
require('./bootstrap.css');
require('./myapp.less');

var img = document.createElement('img');
img.src = require('./glyph.png');
```

CSS (veya less vb.) dosyasına ihtiyaç duyduğunuz zaman webpack, CSS'i JS bundle içerisinde string olarak sıralar ve `require()` sayfanın içerisine `<style>` tag'i ekler. Resim dosyasına ihtiyaç duyduğunuz zaman webpack, resmin URL'ini bundle içerisinde sıralar ve onu `require()` ile döndürür.

Ama webpack'e bunu nasıl yapacağını öğretmeniz gerekir (yine loaders ile):

```js
// webpack.config.js
module.exports = {
  entry: './main.js',
  output: {
    path: './build', // Resim ve js dosyalarının gideceği yer
    publicPath: 'http://mycdn.com/', // Mesela resimlere URL oluşturmak için kullanılır
    filename: 'bundle.js'
  },
  module: {
    loaders: [
      { test: /\.less$/, loader: 'style-loader!css-loader!less-loader' }, // zincirlemek için ! kullanın
      { test: /\.css$/, loader: 'style-loader!css-loader' },
      { test: /\.(png|jpg)$/, loader: 'url-loader?limit=8192' } // <=8k resimler için base64 URL'leri sıralar, geri kalanlar için URL'leri yönlendirir
    ]
  }
};
```

## 6. Bayrakların (flag) özellikleri

Kodu geliştirme süreci ortamları (loglama gibi) ve test sürümü sunucularımız (yayınlanmamış özellikleri çalışanların test etmesi gibi) için sınırlandırmak istiyoruz. Kodunuzda sihirli globallere başvurun.

```js
if (__DEV__) {
  console.warn('Ekstra log');
}
// ...
if (__PRERELEASE__) {
  showSecretFeature();
}
```

Daha sonra webpack'e bu sihirli globalleri öğretin:

```js
// webpack.config.js

// definePlugin ham string'leri alır ve ekler, böylece eğer isterseniz JS string'leri yerleştirebilirsiniz.
var definePlugin = new webpack.DefinePlugin({
  __DEV__: JSON.stringify(JSON.parse(process.env.BUILD_DEV || 'true')),
  __PRERELEASE__: JSON.stringify(JSON.parse(process.env.BUILD_PRERELEASE || 'false'))
});

module.exports = {
  entry: './main.js',
  output: {
    filename: 'bundle.js'       
  },
  plugins: [definePlugin]
};
```

Sonra `BUILD_DEV=1 BUILD_PRERELEASE=1 webpack` ile konsoldan build işlemini gerçekleştirebilirsiniz. Şunu unutmayın `webpack -p` uglify ve dead-code eliminasyonu olduğu için bloklarda saklanan gizli string değerleri dışarı sızdırılmamış olacak.

## 7. Çoklu giriş noktası

Farz edelim ki profile ve feed sayfanız var. Eğer kullanıcı yalnızca profile sayfasını istiyorsa feed sayfası için gerekli olan kodları indirmesini istemezsiniz. Bu yüzden birden çok bundle yapın: her sayfa için bir tane "main module" (giriş noktası) oluşturun:

```js
// webpack.config.js
module.exports = {
  entry: {
    Profile: './profile.js',
    Feed: './feed.js'
  },
  output: {
    path: 'build',
    filename: '[name].js' // Yukarıdaki girdideki anahtarlara dayalı şablon
  }
};
```

Profile için sayfanıza `<script src="build/Profile.js"></script>` ekleyin. Feed sayfası içinde benzer bir şey yapın.

## 8. Ortak kod optimizasyonu

Feed ve profile sayfalarının birçok ortak kodu var (React ve ortak stylesheet ve bileşenler gibi). webpack ortak noktalarını çözümleyebilir ve sayfalar arası önbellekte tutulan bir bundle (shared bundle) oluşturabilir:

```js
// webpack.config.js

var webpack = require('webpack');

var commonsPlugin =
  new webpack.optimize.CommonsChunkPlugin('common.js');

module.exports = {
  entry: {
    Profile: './profile.js',
    Feed: './feed.js'
  },
  output: {
    path: 'build',
    filename: '[name].js' // Yukarıdaki girdideki anahtarlara dayalı şablon
  },
  plugins: [commonsPlugin]
};
```

Bir önceki adımda eklediğiniz script tag'inden önce `<script src="build/common.js"></script>` ekleyin ve kılınızı kıpırdatmadan önbellek kullanmanın tadını çıkarın.

## 9. Asenkron yükleme

CommonJS senkrondur ama webpack ile asenkron olarak bağımlılıkları tanımlamak mümkündür. Bu, her sayfada yönlendirici (router) olmasını istediğiniz client-side yönlendiriciler için kullanışlıdır ama bu özellikleri ihtiyacınız olana kadar indirmek zorun kalmak istemezsiniz.

Asenkron olarak yüklemek istediğiniz **bölünme noktası** tanımlayın.

```js
if (window.location.pathname === '/feed') {
  showLoadingState();
  require.ensure([], function() { // bu sentaks garip ama işe yarıyor
    hideLoadingState();
    require('./feed').show(); // bu fonksiyon çağırıldığında modül'ün senkron olması garantiye alınır.
  });
} else if (window.location.pathname === '/profile') {
  showLoadingState();
  require.ensure([], function() {
    hideLoadingState();
    require('./profile').show();
  });
}
```

webpack geri kalanını sizin için yapacak, ekstra **yığın** dosyaları oluşturacak ve bunları sizin için yükleyecek.

```js
// webpack.config.js
output: {
    path: "/home/proj/public/assets", //webpack'in build yapacağı yol
    publicPath: "/assets/" //require işlemi yapılırken kullanılacak yol
}
```

## Ek kaynaklar

Başarılı bir takımın webpack'i nasıl kullandığını gösteren gerçek bir örneğe göz atın: http://youtu.be/VkTCL6Nqm6Y
Bu, Pete Hunt'ın Instagram.com'daki webpack ile ilgili OSCon'daki konuşmasıdır.

## SSS

### webpack pek modüler değil gibi

webpack, **son derece** modülerdir. webpack'i harika yapan şey, browserify ve requirejs gibi diğer alternatifleriyle karşılaştırıldığında, eklentilerin build işlemi sırasında daha fazla yere enjekte edilmesine izin vermesidir. Çekirdeğe build edilmiş gibi gözüken çoğu şey aslında varsayılan eklentilerdir ve override edilebilir (yani CommonJS require() parser).


================================================
FILE: README-zh.md
================================================
## 本教程的目标

这是一本教你如何应用webpack到你的项目中的工具书。它包含了我们在`Instagram`中用到的绝大多数的内容。

我的建议:这个教程作为你第一个`webpack`的文档,学习完以后去看它的官方文档,了解更详细的说明。

## 学习的前提

  * 你了解过类似`browserify`、`RequireJS`的东西
  * 你知道:
  	* Bundle的拆分
  	* 异步的加载
  	* 打包images和css的这一类的静态资源

## 1. 为什么选择 webpack?


  * **它和browserify类似** 但是它可以把你的应用拆分成多个文件。如果你的单页应用里有很多页面,用户只会下载当前访问页面的代码。当他们访问应用中的其他页面时,不再需要加载与之前页面重复的通用代码。
  * **它可以替代gulp和grunt** 因为他可以构建打包css、预处理css、编译js和图片等。

它支持AMD和CommonJS,以及其他的模块系统(Angular, ES6)。如果你不太熟悉如何使用,就用CommonJS吧。

## 2. 对于习惯Browserify的人可以这样使用Webpack

下面的命令是等价的:

```js
browserify main.js > bundle.js
```

```js
webpack main.js bundle.js
```

然而,webpack要比Browserify强大。所以一般情况下你需要建立一个`webpack.config.js`文件来配置webpack。

```js
// webpack.config.js
module.exports = {
  entry: './main.js',
  output: {
    filename: 'bundle.js'
  }
};
```

这就是单纯的JS,所有写这个配置文件毫无压力。

## 3. 如何调用webpack

选择一个目录下有`webpack.config.js`文件的文件夹,然后运行下面的命令:

  * `webpack` 开发环境下编译
  * `webpack -p` 产品编译及压缩
  * `webpack --watch` 开发环境下持续的监听文件变动来进行编译(非常快!)
  * `webpack -d` 引入 source maps

## 4. 编译js

webpack可以和browserify、RequireJS一样作为一个**loader**(加载工具)来使用。下面我们来看下如何使用webpack去加载、编译CoffeeScript和JSX+ES6。(这里你必须先 `npm install babel-loader coffee-loader`):

你也要看下[babel-loader的介绍](https://www.npmjs.com/package/babel-loader),它会作为一个开发环境下的依赖加载到我们的项目中(run `npm install babel-core babel-preset-es2015 babel-preset-react`)

```js
// webpack.config.js
module.exports = {
  entry: './main.js', // 入口文件
  output: {
    filename: 'bundle.js' // 打包输出的文件
  },
  module: {
    loaders: [
      {
        test: /\.coffee$/,  // test 去判断是否为.coffee的文件,是的话就是进行coffee编译
        loader: 'coffee-loader'
      },
      {
        test: /\.js$/, // test 去判断是否为.js,是的话就是进行es6和jsx的编译
        loader: 'babel-loader',
        query: {
          presets: ['es2015', 'react']
        }
      }
    ]
  }
};
```

如果你希望在require文件时省略文件的扩展名,只需要在webpack.config.js中添加 `resolve.extensions` 来配置。

```js
// webpack.config.js
module.exports = {
  entry: './main.js',
  output: {
    filename: 'bundle.js'
  },
  module: {
    loaders: [
      { test: /\.coffee$/, loader: 'coffee-loader' },
      {
        test: /\.js$/,
        loader: 'babel-loader',
        query: {
          presets: ['es2015', 'react']
        }
      }
    ]
  },
  resolve: {
    // 现在你require文件的时候可以直接使用require('file'),不用使用require('file.coffee')
    extensions: ['', '.js', '.json', '.coffee']
  }
};
```

## 5. Css样式和图片的加载

首先你需要用`require()`去加载你的静态资源(named as they would with node's `require()`):

```js
require('./bootstrap.css');
require('./myapp.less');

var img = document.createElement('img');
img.src = require('./glyph.png');
```

当你require了CSS(less或者其他)文件,webpack会在页面中插入一个内联的`<style>`,去引入样式。当require图片的时候,bundle文件会包含图片的url,并通过`require()`返回图片的url。

但是这需要你在`webpack.config.js`做相应的配置(这里还是使用loaders)

```js
// webpack.config.js
module.exports = {
  entry: './main.js',
  output: {
    path: './build', // 图片和js会放在这
    publicPath: 'http://mycdn.com/', // 这里用来生成图片的地址
    filename: 'bundle.js'
  },
  module: {
    loaders: [
      { test: /\.less$/, loader: 'style-loader!css-loader!less-loader' }, // 用!去链式调用loader
      { test: /\.css$/, loader: 'style-loader!css-loader' },
      {test: /\.(png|jpg)$/, loader: 'url-loader?limit=8192'} // 内联的base64的图片地址,图片要小于8k,直接的url的地址则不解析
    ]
  }
};
```

## 6. 功能标识(Feature flags)

项目中有些代码我们只为在开发环境(例如日志)或者是内部测试环境(例如那些没有发布的新功能)中使用,那就需要引入下面这些魔法全局变量(magic globals):

```js
if (__DEV__) {
  console.warn('Extra logging');
}
// ...
if (__PRERELEASE__) {
  showSecretFeature();
}
```

同时还要在webpack.config.js中配置这些变量,使得webpack能够识别他们。

```js
// webpack.config.js

// definePlugin 会把定义的string 变量插入到Js代码中。
var definePlugin = new webpack.DefinePlugin({
  __DEV__: JSON.stringify(JSON.parse(process.env.BUILD_DEV || 'true')),
  __PRERELEASE__: JSON.stringify(JSON.parse(process.env.BUILD_PRERELEASE || 'false'))
});

module.exports = {
  entry: './main.js',
  output: {
    filename: 'bundle.js'
  },
  plugins: [definePlugin]
};
```

配置完成后,就可以使用 `BUILD_DEV=1 BUILD_PRERELEASE=1 webpack`来打包代码了。
值得注意的是,`webpack -p` 会删除所有无作用代码,也就是说那些包裹在这些全局变量下的代码块都会被删除,这样就能保证这些代码不会因发布上线而泄露。

## 7. 多个入口文件

如果你有两个页面:profile和feed。如果你希望用户访问profile页面时不加载feed页面的代码,那就需要生成多个bundles文件:为每个页面创建自己的“main module”(入口文件)。

```js
// webpack.config.js
module.exports = {
  entry: {
    Profile: './profile.js',
    Feed: './feed.js'
  },
  output: {
    path: 'build',
    filename: '[name].js' // name是基于上边entry中定义的key
  }
};
```

在profile页面中插入`<script src="build/Profile.js"></script>`。feed也一样。

## 8. 优化通用代码

Feed和Profile页面存在大量通用代码(比如React、公共的样式和组件等等)。webpack可以抽离页面间公共的代码,生成一个公共的bundle文件,供这两个页面缓存使用:

```js
// webpack.config.js

var webpack = require('webpack');

var commonsPlugin =
  new webpack.optimize.CommonsChunkPlugin('common.js'); // 引入插件

module.exports = {
  entry: {
    Profile: './profile.js',
    Feed: './feed.js'
  },
  output: {
    path: 'build',
    filename: '[name].js' // 为上面entry的key值
  },
  plugins: [commonsPlugin]
};
```

在上一步引入自己的bundle之前引入`<script src="build/common.js"></script>`

## 9. 异步加载

虽然CommonJS是同步加载的,但是webpack也提供了异步加载的方式。这对于单页应用中使用的客户端路由非常有用。当真正路由到了某个页面的时候,它的代码才会被加载下来。

指定你要异步加载的 **拆分点**。看下面的例子

```js
if (window.location.pathname === '/feed') {
  showLoadingState();
  require.ensure([], function() { // 这个语法痕奇怪,但是还是可以起作用的
    hideLoadingState();
    require('./feed').show(); // 当这个函数被调用的时候,此模块是一定已经被同步加载下来了
  });
} else if (window.location.pathname === '/profile') {
  showLoadingState();
  require.ensure([], function() {
    hideLoadingState();
    require('./profile').show();
  });
}
```

剩下的事就可以交给webpack,它会为你生成并加载这些额外的 **chunk** 文件。

webpack 默认会从项目的根目录下引入这些chunk文件。你也可以通过 `output.publicPath`来配置chunk文件的引入路径

```js
// webpack.config.js
output: {
    path: "/home/proj/public/assets", // webpack的build路径
    publicPath: "/assets/" // 你require的路径
}
```

## 其他

看一个真实的例子,[看看他们是怎么使用webpack](http://youtu.be/VkTCL6Nqm6Y)。这是Pete Hunt在Instagram.com中谈论webpack的视频。

## FAQ

### webpack 不仅仅是个modular

相比较browserify和browserify,在你的项目中大量的使用webpack插件才能体现出webpack的优势。当使用了插件后,代码才会被复写。其余的都是默认加载。


================================================
FILE: README.md
================================================
# webpack-howto

## Goal of this guide

This is a cookbook of how to get things done with webpack. This includes most things we use at Instagram and nothing we don't use.

My advice: start with this as your webpack docs, then look at the official docs for clarification.

## Prerequisites

  * You know browserify, RequireJS or something similar
  * You see the value in:
    * Bundle splitting
    * Async loading
    * Packaging static assets like images and CSS

## 1. Why webpack?


  * **It's like browserify** but can split your app into multiple files. If you have multiple pages in a single-page app, the user only downloads code for just that page. If they go to another page, they don't redownload common code.

  * **It often replaces grunt or gulp** because it can build and bundle CSS, preprocessed CSS, compile-to-JS languages and images, among other things.

It supports AMD and CommonJS, among other module systems (Angular, ES6). If you don't know what to use, use CommonJS.

## 2. Webpack for Browserify people

These are equivalent:

```js
browserify main.js > bundle.js
```

```js
webpack main.js bundle.js
```

However, webpack is more powerful than Browserify, so you generally want to make a `webpack.config.js` to keep things organized:

```js
// webpack.config.js
module.exports = {
  entry: './main.js',
  output: {
    filename: 'bundle.js'       
  }
};
```

This is just JS, so feel free to put Real Code in there.

## 3. How to invoke webpack

Switch to the directory containing `webpack.config.js` and run:

  * `webpack` for building once for development
  * `webpack -p` for building once for production (minification)
  * `webpack --watch` for continuous incremental build in development (fast!)
  * `webpack -d` to include source maps

## 4. Compile-to-JS languages

webpack's equivalent of browserify transforms and RequireJS plugins is a **loader**. Here's how you can teach webpack to load CoffeeScript and Facebook JSX+ES6 support (you must `npm install babel-loader coffee-loader`):

See also the [babel-loader installation instructions](https://www.npmjs.com/package/babel-loader) for additional dependencies (tl;dr run `npm install babel-core babel-preset-es2015 babel-preset-react`).

```js
// webpack.config.js
module.exports = {
  entry: './main.js',
  output: {
    filename: 'bundle.js'       
  },
  module: {
    loaders: [
      { test: /\.coffee$/, loader: 'coffee-loader' },
      {
        test: /\.js$/,
        loader: 'babel-loader',
        query: {
          presets: ['es2015', 'react']
        }
      }
    ]
  }
};
```

To enable requiring files without specifying the extension, you must add a `resolve.extensions` parameter specifying which files webpack searches for:

```js
// webpack.config.js
module.exports = {
  entry: './main.js',
  output: {
    filename: 'bundle.js'       
  },
  module: {
    loaders: [
      { test: /\.coffee$/, loader: 'coffee-loader' },
      {
        test: /\.js$/,
        loader: 'babel-loader',
        query: {
          presets: ['es2015', 'react']
        }
      }
    ]
  },
  resolve: {
    // you can now require('file') instead of require('file.coffee')
    extensions: ['', '.js', '.json', '.coffee'] 
  }
};
```


## 5. Stylesheets and images

First update your code to `require()` your static assets (named as they would with node's `require()`):

```js
require('./bootstrap.css');
require('./myapp.less');

var img = document.createElement('img');
img.src = require('./glyph.png');
```

When you require CSS (or less, etc), webpack inlines the CSS as a string inside the JS bundle and `require()` will insert a `<style>` tag into the page. When you require images, webpack inlines a URL to the image into the bundle and returns it from `require()`.

But you need to teach webpack to do this (again, with loaders):

```js
// webpack.config.js
module.exports = {
  entry: './main.js',
  output: {
    path: './build', // This is where images AND js will go
    publicPath: 'http://mycdn.com/', // This is used to generate URLs to e.g. images
    filename: 'bundle.js'
  },
  module: {
    loaders: [
      { test: /\.less$/, loader: 'style-loader!css-loader!less-loader' }, // use ! to chain loaders
      { test: /\.css$/, loader: 'style-loader!css-loader' },
      { test: /\.(png|jpg)$/, loader: 'url-loader?limit=8192' } // inline base64 URLs for <=8k images, direct URLs for the rest
    ]
  }
};
```

## 6. Feature flags

We have code we want to gate only to our dev environments (like logging) and our internal dogfooding servers (like unreleased features we're testing with employees). In your code, refer to magic globals:

```js
if (__DEV__) {
  console.warn('Extra logging');
}
// ...
if (__PRERELEASE__) {
  showSecretFeature();
}
```

Then teach webpack those magic globals:

```js
// webpack.config.js

// definePlugin takes raw strings and inserts them, so you can put strings of JS if you want.
var definePlugin = new webpack.DefinePlugin({
  __DEV__: JSON.stringify(JSON.parse(process.env.BUILD_DEV || 'true')),
  __PRERELEASE__: JSON.stringify(JSON.parse(process.env.BUILD_PRERELEASE || 'false'))
});

module.exports = {
  entry: './main.js',
  output: {
    filename: 'bundle.js'       
  },
  plugins: [definePlugin]
};
```

Then you can build with `BUILD_DEV=1 BUILD_PRERELEASE=1 webpack` from the console. Note that since `webpack -p` runs uglify dead-code elimination, anything wrapped in one of these blocks will be stripped out, so you won't leak secret features or strings.

## 7. Multiple entrypoints

Let's say you have a profile page and a feed page. You don't want to make the user download the code for the feed if they just want the profile. So make multiple bundles: create one "main module" (called an entrypoint) per page:

```js
// webpack.config.js
module.exports = {
  entry: {
    Profile: './profile.js',
    Feed: './feed.js'
  },
  output: {
    path: 'build',
    filename: '[name].js' // Template based on keys in entry above
  }
};
```

For profile, insert `<script src="build/Profile.js"></script>` into your page. Do a similar thing for feed.

## 8. Optimizing common code

Feed and Profile share a lot in common (like React and the common stylesheets and components). webpack can figure out what they have in common and make a shared bundle that can be cached between pages:

```js
// webpack.config.js

var webpack = require('webpack');

var commonsPlugin =
  new webpack.optimize.CommonsChunkPlugin('common.js');

module.exports = {
  entry: {
    Profile: './profile.js',
    Feed: './feed.js'
  },
  output: {
    path: 'build',
    filename: '[name].js' // Template based on keys in entry above
  },
  plugins: [commonsPlugin]
};
```

Add `<script src="build/common.js"></script>` before the script tag you added in the previous step and enjoy the free caching.

## 9. Async loading

CommonJS is synchronous but webpack provides a way to asynchronously specify dependencies. This is useful for client-side routers, where you want the router on every page, but you don't want to have to download features until you actually need them.

Specify the **split point** where you want to load asynchronously. For example:

```js
if (window.location.pathname === '/feed') {
  showLoadingState();
  require.ensure([], function() { // this syntax is weird but it works
    hideLoadingState();
    require('./feed').show(); // when this function is called, the module is guaranteed to be synchronously available.
  });
} else if (window.location.pathname === '/profile') {
  showLoadingState();
  require.ensure([], function() {
    hideLoadingState();
    require('./profile').show();
  });
}
```

webpack will do the rest and generate extra **chunk** files and load them for you.

webpack will assume that those files are in your root directory when you load then into a html script tag for example. You can use `output.publicPath` to configure that.

```js
// webpack.config.js
output: {
    path: "/home/proj/public/assets", //path to where webpack will build your stuff
    publicPath: "/assets/" //path that will be considered when requiring your files
}
```

## Additional resources

Take a look at a real world example on how a successful team is leveraging webpack: http://youtu.be/VkTCL6Nqm6Y
This is Pete Hunt at OSCon talking about webpack at Instagram.com

## FAQ

### webpack doesn't seem modular

webpack is **extremely** modular. What makes webpack great is that it lets plugins inject themselves into more places in the build process when compared to alternatives like browserify and requirejs. Many things that may seem built into the core are just plugins that are loaded by default and can be overridden (i.e. the CommonJS require() parser).


================================================
FILE: example/.gitignore
================================================
node_modules
*.log
bundle.js


================================================
FILE: example/index.html
================================================
<html>
  <body></body>
  <script src="bundle.js"></script>
</html>


================================================
FILE: example/modules/About.js
================================================
var React = require('react');

var About = React.createClass({
  render: function() {
    return (
      <div>About</div>
    );
  }
});

module.exports = About;


================================================
FILE: example/modules/App.css
================================================
body {
  font-family: 'Comic sans';
}

================================================
FILE: example/modules/App.js
================================================
var React = require('react');
var {Link, RouteHandler} = require('react-router');

require('./App.css');

var App = React.createClass({
  render: function() {
    return (
      <div>
        <header>
          <ul>
            <li><Link to="home">Home</Link></li>
            <li><Link to="about">About</Link></li>
          </ul>
        </header>

        <RouteHandler />
      </div>
    );
  }
});

module.exports = App;


================================================
FILE: example/modules/Home.js
================================================
var React = require('react');

var Home = React.createClass({
  render: function() {
    return (
      <div>Home</div>
    );
  }
});

module.exports = Home;


================================================
FILE: example/modules/main.js
================================================
var App = require('./App');
var Home = require('./Home');
var About = require('./About');
var React = require('react');
var Router = require('react-router');
var {DefaultRoute, Route, Routes} = Router;

var routes = (
  <Route name="app" path="/" handler={App}>
    <Route name="about" handler={About} />
    <DefaultRoute name="home" handler={Home} />
  </Route>
);

Router.run(routes, Router.HistoryLocation, function(Handler) {
  React.render(<Handler/>, document.body);
});


================================================
FILE: example/package.json
================================================
{
  "name": "webpack-howto-example",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "start": "webpack-dev-server",
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "author": "",
  "license": "ISC",
  "devDependencies": {
    "babel-core": "^5.8.23",
    "babel-loader": "^5.3.2",
    "bundle-loader": "^0.5.0",
    "css-loader": "^0.9.0",
    "file-loader": "^0.7.2",
    "less": "^1.7.5",
    "less-loader": "^0.7.7",
    "style-loader": "^0.8.0",
    "url-loader": "^0.5.5",
    "webpack-dev-server": "^1.6.5"
  },
  "dependencies": {
    "react": "^0.13.3",
    "react-router": "^0.13.3"
  }
}


================================================
FILE: example/webpack.config.js
================================================
module.exports = {
  entry: './modules/main.js',
  output: {
    filename: 'bundle.js'
  },
  module: {
    loaders: [
      {
        test: /\.js$/,
        loader: 'babel-loader',
        query: {
          presets: ['es2015', 'react']
        }
      },
      { test: /\.less$/, loader: 'style-loader!css-loader!less-loader' }, // use ! to chain loaders
      { test: /\.css$/, loader: 'style-loader!css-loader' },
      { test: /\.(png|jpg)$/, loader: 'url-loader?limit=8192' } // inline base64 URLs for <=8k images, direct URLs for the rest
    ]
  }
};
Download .txt
gitextract_luql2mqu/

├── README-es.md
├── README-tr.md
├── README-zh.md
├── README.md
└── example/
    ├── .gitignore
    ├── index.html
    ├── modules/
    │   ├── About.js
    │   ├── App.css
    │   ├── App.js
    │   ├── Home.js
    │   └── main.js
    ├── package.json
    └── webpack.config.js
Condensed preview — 13 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (38K chars).
[
  {
    "path": "README-es.md",
    "chars": 9700,
    "preview": "# webpack-howto\n\n## Objetivo de esta guía\n\nEsta es una guía sobre como lograr lo que uno quiere usando webpack. Incluye "
  },
  {
    "path": "README-tr.md",
    "chars": 9127,
    "preview": "# webpack-howto\n\n## Bu kılavuzun amacı\n\nBu kıtapçık, webpack ile işlerin nasıl yürüdüğünü gösterir. Instagram'da kulland"
  },
  {
    "path": "README-zh.md",
    "chars": 6004,
    "preview": "## 本教程的目标\n\n这是一本教你如何应用webpack到你的项目中的工具书。它包含了我们在`Instagram`中用到的绝大多数的内容。\n\n我的建议:这个教程作为你第一个`webpack`的文档,学习完以后去看它的官方文档,了解更详细的说"
  },
  {
    "path": "README.md",
    "chars": 8715,
    "preview": "# webpack-howto\n\n## Goal of this guide\n\nThis is a cookbook of how to get things done with webpack. This includes most th"
  },
  {
    "path": "example/.gitignore",
    "chars": 29,
    "preview": "node_modules\n*.log\nbundle.js\n"
  },
  {
    "path": "example/index.html",
    "chars": 67,
    "preview": "<html>\n  <body></body>\n  <script src=\"bundle.js\"></script>\n</html>\n"
  },
  {
    "path": "example/modules/About.js",
    "chars": 162,
    "preview": "var React = require('react');\n\nvar About = React.createClass({\n  render: function() {\n    return (\n      <div>About</div"
  },
  {
    "path": "example/modules/App.css",
    "chars": 37,
    "preview": "body {\n  font-family: 'Comic sans';\n}"
  },
  {
    "path": "example/modules/App.js",
    "chars": 427,
    "preview": "var React = require('react');\nvar {Link, RouteHandler} = require('react-router');\n\nrequire('./App.css');\n\nvar App = Reac"
  },
  {
    "path": "example/modules/Home.js",
    "chars": 159,
    "preview": "var React = require('react');\n\nvar Home = React.createClass({\n  render: function() {\n    return (\n      <div>Home</div>\n"
  },
  {
    "path": "example/modules/main.js",
    "chars": 478,
    "preview": "var App = require('./App');\nvar Home = require('./Home');\nvar About = require('./About');\nvar React = require('react');\n"
  },
  {
    "path": "example/package.json",
    "chars": 650,
    "preview": "{\n  \"name\": \"webpack-howto-example\",\n  \"version\": \"1.0.0\",\n  \"description\": \"\",\n  \"main\": \"index.js\",\n  \"scripts\": {\n   "
  },
  {
    "path": "example/webpack.config.js",
    "chars": 559,
    "preview": "module.exports = {\n  entry: './modules/main.js',\n  output: {\n    filename: 'bundle.js'\n  },\n  module: {\n    loaders: [\n "
  }
]

About this extraction

This page contains the full source code of the petehunt/webpack-howto GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 13 files (35.3 KB), approximately 10.2k tokens. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.

Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.

Copied to clipboard!