A vertex shader:

    //WebGL Vertex Shader
    
    uniform mat4 uMVMatrix;             // Model-view matrix
    uniform mat4 uPMatrix;              // Projection matrix
    uniform mat4 uNMatrix;              // Normal matrix
    
    attribute vec3 aVertexPosition;     // Vertex position in object space
    attribute vec3 aVertexNormal;       // Vertex normal in object space
    
    varying vec3 vPosition;             // Vertex position (camera space)
    varying vec3 vNormal;               // Vertex normal (camera space)
    
    void main(void) {
        vec4 camSpacePosition = uMVMatrix * vec4(aVertexPosition, 1.0);
        vPosition = vec3(camSpacePosition);
    
        gl_Position = uPMatrix * camSpacePosition;        
    
        vec4 camSpaceNormal = uNMatrix * vec4(aVertexNormal, 0.0);
        vNormal = vec3(camSpaceNormal);
    }

Three.js has built-in attributes, so:

    //Three.js Vertex Shader
    
    /*
    built-in attributes and uniforms
    ===============================
    uMVMatrix -> modelViewMatrix
    uPMatrix -> projectionMatrix
    uNMatrix -> normalMatrix
    
    aVertexPosition -> position
    aVertexNormal -> normal
    ===============================
    */
    
    varying vec3 vPosition;             // Vertex position (camera space)
    varying vec3 vNormal;               // Vertex normal (camera space)
    
    void main(void) {
        vec4 camSpacePosition = modelViewMatrix * vec4(position, 1.0);
        vPosition = vec3(camSpacePosition);
        
        gl_Position = projectionMatrix * camSpacePosition;
        
        vec4 camSpaceNormal = normalMatrix * vec4(normal, 1.0);
        vNormal = vec3(camSpaceNormal)
    }

Example: Phong Shading

viewing: $\hat{o}= \frac{p}{|p|}$

reflected direction: $\hat{r} = 2 \hat{n} \langle \hat{n}, \hat{i} \rangle - \hat{i}$

fragColor= \left { \begin{array}{ll} k_{d} ( I \cdot \langle \hat{n} , \hat{i} \rangle) + I \cdot max(\langle \hat{o}, \hat{r} \rangle, 0)^{\alpha} , \qquad \langle \hat{n}, \hat{i}\rangle > 0 \
k_{d}c_{0}\
\end{array} \right

    //WebGL Fragment Shader (or Three.js)
    
    precision mediump float;
    
    // the uniform can be defined in custome shaderMaterial
    
    uniform vec3 uLightPos;             // Light position in camera space
    uniform float uLightPower;          // Light power
    uniform vec3 uDiffuseColor;         // Diffuse color
    uniform float uExponent;            // Phong exponent
    uniform float uAmbient;             // Ambient
    
    varying vec3 vPosition;             // Fragment position (camera space)
    varying vec3 vNormal;               // Fragment normal (camera space)
    
    void main(void) {
        vec3 L = normalize(uLightPos - vPosition);      // i, light direction
        vec3 N = normalize(vNormal);                    // n, normalized normal vector
        vec3 V = -normalize(vPosition);                 // o, viewing direction
        vec3 R = normalize(-reflect(L, N));             // r, reflected direction
    
        float intensity = uLightPower/(pow(length(uLightPos - vPosition), 2.0)/5.0+5.0);
        vec3 color;
    
        if (dot(N, L) > 0.0)
        {
            color = uDiffuseColor * (intensity * dot(N, L) + uAmbient);
            color += intensity * pow(max(dot(V, R), 0.0), uExponent);
        }
        else
        {
            color = uDiffuseColor * uAmbient;
        }
    
        gl_FragColor = vec4(color, 1.0);
    }